@huicai/cli 2026.814.0 → 2026.1021.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +391 -32
- package/README.md +139 -8
- package/bin/huicai.js +155 -74
- package/bin/update.js +97 -0
- package/package.json +27 -8
- package/skills/ab-testing/trigger-cases.json +30 -0
- package/skills/academic-writing/trigger-cases.json +30 -0
- package/skills/accounting-ops/trigger-cases.json +30 -0
- package/skills/ai-agent/trigger-cases.json +30 -0
- package/skills/ai-aiops/trigger-cases.json +30 -0
- package/skills/ai-coding/SKILL.md +2 -0
- package/skills/ai-coding/trigger-cases.json +30 -0
- package/skills/ai-compliance/trigger-cases.json +30 -0
- package/skills/ai-eval/trigger-cases.json +30 -0
- package/skills/ai-llm-app/trigger-cases.json +30 -0
- package/skills/ai-mlops/trigger-cases.json +30 -0
- package/skills/ai-multimodal/trigger-cases.json +30 -0
- package/skills/ai-prompt/trigger-cases.json +30 -0
- package/skills/ai-rag/trigger-cases.json +30 -0
- package/skills/anomaly-detection/trigger-cases.json +30 -0
- package/skills/api-design/trigger-cases.json +31 -0
- package/skills/api-integration/trigger-cases.json +31 -0
- package/skills/arch-design/trigger-cases.json +12 -0
- package/skills/arch-diagram/SKILL.md +118 -0
- package/skills/arch-diagram/trigger-cases.json +30 -0
- package/skills/arch-distributed/trigger-cases.json +30 -0
- package/skills/arch-multitenant/trigger-cases.json +30 -0
- package/skills/audio-brief/SKILL.md +65 -0
- package/skills/audio-brief/trigger-cases.json +30 -0
- package/skills/audit-assist/trigger-cases.json +30 -0
- package/skills/audit-chain/trigger-cases.json +31 -0
- package/skills/banking-credit/trigger-cases.json +30 -0
- package/skills/brand-design/trigger-cases.json +30 -0
- package/skills/business-plan/trigger-cases.json +30 -0
- package/skills/capital-ops/trigger-cases.json +30 -0
- package/skills/cicd-pipeline/trigger-cases.json +31 -0
- package/skills/code-archaeology/SKILL.md +55 -0
- package/skills/code-archaeology/trigger-cases.json +9 -0
- package/skills/code-quality/SKILL.md +138 -0
- package/skills/code-quality/references/languages.md +107 -0
- package/skills/code-quality/scripts/__pycache__/code_battery.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_check.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_check.cpython-313.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_csharp.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_csharp.cpython-313.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_fix.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_fix.cpython-313.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_java.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_java.cpython-313.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_jsts.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_jsts.cpython-313.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_lens.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_lens.cpython-313.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_python.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_python.cpython-313.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_testplan.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/code_battery.py +1072 -0
- package/skills/code-quality/scripts/code_check.py +1269 -0
- package/skills/code-quality/scripts/code_csharp.py +371 -0
- package/skills/code-quality/scripts/code_fix.py +201 -0
- package/skills/code-quality/scripts/code_java.py +695 -0
- package/skills/code-quality/scripts/code_jsts.py +313 -0
- package/skills/code-quality/scripts/code_lens.py +1079 -0
- package/skills/code-quality/scripts/code_python.py +536 -0
- package/skills/code-quality/scripts/code_testplan.py +239 -0
- package/skills/code-quality/trigger-cases.json +45 -0
- package/skills/code-review/SKILL.md +24 -0
- package/skills/code-review/trigger-cases.json +35 -0
- package/skills/commit-and-pr/trigger-cases.json +31 -0
- package/skills/content-creation/trigger-cases.json +30 -0
- package/skills/corporate-governance/trigger-cases.json +30 -0
- package/skills/crawl-chain/trigger-cases.json +31 -0
- package/skills/customer-service/trigger-cases.json +30 -0
- package/skills/data-analysis/trigger-cases.json +30 -0
- package/skills/data-chain/SKILL.md +1 -1
- package/skills/data-chain/trigger-cases.json +31 -0
- package/skills/data-governance/trigger-cases.json +30 -0
- package/skills/data-report-pro/trigger-cases.json +30 -0
- package/skills/data-streaming/trigger-cases.json +30 -0
- package/skills/data-wrangling/SKILL.md +1 -1
- package/skills/data-wrangling/trigger-cases.json +30 -0
- package/skills/db-es/trigger-cases.json +30 -0
- package/skills/db-migration/trigger-cases.json +30 -0
- package/skills/db-mysql/trigger-cases.json +30 -0
- package/skills/db-postgres/trigger-cases.json +30 -0
- package/skills/db-redis/trigger-cases.json +30 -0
- package/skills/debug-root-cause/trigger-cases.json +30 -0
- package/skills/dependency-audit/SKILL.md +56 -0
- package/skills/dependency-audit/trigger-cases.json +7 -0
- package/skills/dependency-upgrade/trigger-cases.json +31 -0
- package/skills/dev-cpp/trigger-cases.json +30 -0
- package/skills/dev-cross-platform/trigger-cases.json +30 -0
- package/skills/dev-csharp/SKILL.md +23 -0
- package/skills/dev-csharp/trigger-cases.json +30 -0
- package/skills/dev-frontend/SKILL.md +19 -0
- package/skills/dev-frontend/trigger-cases.json +30 -0
- package/skills/dev-go/trigger-cases.json +30 -0
- package/skills/dev-harmony/trigger-cases.json +30 -0
- package/skills/dev-java/SKILL.md +20 -0
- package/skills/dev-java/trigger-cases.json +30 -0
- package/skills/dev-mobile/trigger-cases.json +30 -0
- package/skills/dev-node/trigger-cases.json +30 -0
- package/skills/dev-php/trigger-cases.json +30 -0
- package/skills/dev-python/SKILL.md +21 -0
- package/skills/dev-python/trigger-cases.json +30 -0
- package/skills/dev-rust/trigger-cases.json +30 -0
- package/skills/dev-toolchain/trigger-cases.json +31 -0
- package/skills/doc-chain/trigger-cases.json +31 -0
- package/skills/doc-compare/trigger-cases.json +30 -0
- package/skills/docx-author/SKILL.md +127 -25
- package/skills/docx-author/scripts/__pycache__/docx_battery.cpython-312.pyc +0 -0
- package/skills/docx-author/scripts/__pycache__/docx_build.cpython-312.pyc +0 -0
- package/skills/docx-author/scripts/__pycache__/docx_check.cpython-312.pyc +0 -0
- package/skills/docx-author/scripts/__pycache__/docx_layout.cpython-312.pyc +0 -0
- package/skills/docx-author/scripts/__pycache__/zh_prose.cpython-312.pyc +0 -0
- package/skills/docx-author/scripts/docx_battery.py +586 -0
- package/skills/docx-author/scripts/docx_build.py +995 -0
- package/skills/docx-author/scripts/docx_check.py +1306 -0
- package/skills/docx-author/scripts/docx_doc.py +14 -154
- package/skills/docx-author/scripts/docx_layout.py +490 -0
- package/skills/docx-author/scripts/zh_prose.py +639 -0
- package/skills/docx-author/trigger-cases.json +58 -0
- package/skills/echo-brief/SKILL.md +84 -0
- package/skills/echo-brief/references/echo-format.md +68 -0
- package/skills/echo-brief/trigger-cases.json +40 -0
- package/skills/ecommerce-ops/trigger-cases.json +30 -0
- package/skills/education-training/trigger-cases.json +30 -0
- package/skills/ehs-safety/trigger-cases.json +30 -0
- package/skills/email-writing/trigger-cases.json +30 -0
- package/skills/eng-ai/trigger-cases.json +30 -0
- package/skills/eng-architecture/trigger-cases.json +31 -0
- package/skills/eng-automation/trigger-cases.json +31 -0
- package/skills/eng-collaboration/trigger-cases.json +30 -0
- package/skills/eng-complex-env/trigger-cases.json +30 -0
- package/skills/eng-data-platform/trigger-cases.json +31 -0
- package/skills/eng-database/trigger-cases.json +31 -0
- package/skills/eng-develop/SKILL.md +9 -1
- package/skills/eng-develop/references/dod-checklist.md +3 -0
- package/skills/eng-develop/references/engineering-workflow.md +37 -0
- package/skills/eng-develop/trigger-cases.json +30 -0
- package/skills/eng-docs/SKILL.md +24 -0
- package/skills/eng-docs/trigger-cases.json +30 -0
- package/skills/eng-efficiency/trigger-cases.json +30 -0
- package/skills/eng-infra/trigger-cases.json +30 -0
- package/skills/eng-integration/trigger-cases.json +31 -0
- package/skills/eng-legacy/trigger-cases.json +31 -0
- package/skills/eng-observability/trigger-cases.json +31 -0
- package/skills/eng-ops/trigger-cases.json +31 -0
- package/skills/eng-performance/trigger-cases.json +31 -0
- package/skills/eng-planning/trigger-cases.json +31 -0
- package/skills/eng-quality/SKILL.md +8 -0
- package/skills/eng-quality/trigger-cases.json +31 -0
- package/skills/eng-release/trigger-cases.json +31 -0
- package/skills/eng-reliability/trigger-cases.json +31 -0
- package/skills/eng-requirements/trigger-cases.json +12 -0
- package/skills/eng-research/trigger-cases.json +30 -0
- package/skills/eng-security/trigger-cases.json +31 -0
- package/skills/eng-ux/trigger-cases.json +30 -0
- package/skills/engineering-chain/trigger-cases.json +30 -0
- package/skills/env-offline/trigger-cases.json +31 -0
- package/skills/env-private-deploy/trigger-cases.json +31 -0
- package/skills/env-xinchuang/trigger-cases.json +31 -0
- package/skills/equipment-tpm/trigger-cases.json +30 -0
- package/skills/esg-report/trigger-cases.json +30 -0
- package/skills/event-management/trigger-cases.json +30 -0
- package/skills/excel-analysis-chain/SKILL.md +17 -4
- package/skills/excel-analysis-chain/trigger-cases.json +31 -0
- package/skills/explain-codebase/trigger-cases.json +11 -0
- package/skills/file-ingest/trigger-cases.json +30 -0
- package/skills/finance-analysis/trigger-cases.json +31 -0
- package/skills/finance-chain/trigger-cases.json +31 -0
- package/skills/financial-modeling/trigger-cases.json +31 -0
- package/skills/find-simplifications/SKILL.md +43 -0
- package/skills/find-simplifications/trigger-cases.json +23 -0
- package/skills/foreign-trade/trigger-cases.json +30 -0
- package/skills/funnel-cohort/trigger-cases.json +30 -0
- package/skills/gov-document/trigger-cases.json +30 -0
- package/skills/gui-change-evidence/SKILL.md +47 -0
- package/skills/gui-change-evidence/trigger-cases.json +23 -0
- package/skills/hr-chain/trigger-cases.json +31 -0
- package/skills/hr-operations/trigger-cases.json +30 -0
- package/skills/info-disclosure/trigger-cases.json +31 -0
- package/skills/infra-gateway/trigger-cases.json +31 -0
- package/skills/infra-k8s/trigger-cases.json +31 -0
- package/skills/infra-mq/trigger-cases.json +30 -0
- package/skills/insurance-advisory/trigger-cases.json +30 -0
- package/skills/internal-audit/trigger-cases.json +30 -0
- package/skills/ip-management/trigger-cases.json +31 -0
- package/skills/ipo-listing/trigger-cases.json +31 -0
- package/skills/it-audit/trigger-cases.json +31 -0
- package/skills/itsm-ops/trigger-cases.json +31 -0
- package/skills/knowledge-sop/trigger-cases.json +31 -0
- package/skills/legal-chain/trigger-cases.json +31 -0
- package/skills/legal-contract/trigger-cases.json +30 -0
- package/skills/litigation-support/trigger-cases.json +31 -0
- package/skills/logistics-warehouse/trigger-cases.json +30 -0
- package/skills/long-doc-analysis/trigger-cases.json +31 -0
- package/skills/management-accounting/trigger-cases.json +30 -0
- package/skills/manufacturing-chain/trigger-cases.json +31 -0
- package/skills/manufacturing-quality/trigger-cases.json +30 -0
- package/skills/marketing-analytics/trigger-cases.json +31 -0
- package/skills/marketing-chain/trigger-cases.json +31 -0
- package/skills/meeting-minutes/trigger-cases.json +30 -0
- package/skills/metrics-system/trigger-cases.json +31 -0
- package/skills/negotiation-prep/trigger-cases.json +30 -0
- package/skills/obs-prometheus/trigger-cases.json +31 -0
- package/skills/office-automation/trigger-cases.json +31 -0
- package/skills/okr-review/trigger-cases.json +30 -0
- package/skills/ops-fleet/trigger-cases.json +31 -0
- package/skills/ops-linux/trigger-cases.json +31 -0
- package/skills/optimization-solver/trigger-cases.json +30 -0
- package/skills/patent-disclosure/SKILL.md +105 -0
- package/skills/patent-disclosure/references/figures.md +110 -0
- package/skills/patent-disclosure/references/outline.md +162 -0
- package/skills/patent-disclosure/scripts/patent_docx.py +230 -0
- package/skills/patent-disclosure/trigger-cases.json +31 -0
- package/skills/patent-drafting/SKILL.md +108 -0
- package/skills/patent-drafting/trigger-cases.json +31 -0
- package/skills/patent-portfolio/SKILL.md +81 -0
- package/skills/patent-portfolio/trigger-cases.json +31 -0
- package/skills/pdf-toolkit/trigger-cases.json +31 -0
- package/skills/perf-optimize/trigger-cases.json +31 -0
- package/skills/pivot-crosstab/trigger-cases.json +30 -0
- package/skills/policy-analysis/trigger-cases.json +31 -0
- package/skills/portfolio-analysis/trigger-cases.json +31 -0
- package/skills/ppt-chain/SKILL.md +14 -6
- package/skills/ppt-chain/trigger-cases.json +31 -0
- package/skills/pptx-author/SKILL.md +86 -33
- package/skills/pptx-author/scripts/__pycache__/pptx_check.cpython-312.pyc +0 -0
- package/skills/pptx-author/scripts/__pycache__/pptx_deck.cpython-312.pyc +0 -0
- package/skills/pptx-author/scripts/__pycache__/pptx_layout.cpython-312.pyc +0 -0
- package/skills/pptx-author/scripts/pptx_battery.py +178 -0
- package/skills/pptx-author/scripts/pptx_build.py +119 -0
- package/skills/pptx-author/scripts/pptx_check.py +1182 -0
- package/skills/pptx-author/scripts/pptx_deck.py +736 -145
- package/skills/pptx-author/scripts/pptx_layout.py +384 -0
- package/skills/pptx-author/trigger-cases.json +15 -0
- package/skills/pr-comms/trigger-cases.json +30 -0
- package/skills/procurement-supply/trigger-cases.json +31 -0
- package/skills/product-design/trigger-cases.json +31 -0
- package/skills/production-planning/trigger-cases.json +31 -0
- package/skills/project-management/trigger-cases.json +31 -0
- package/skills/project-proposal/trigger-cases.json +31 -0
- package/skills/prose-standard/SKILL.md +53 -0
- package/skills/prose-standard/trigger-cases.json +23 -0
- package/skills/qa-api-automation/trigger-cases.json +31 -0
- package/skills/qa-mobile-automation/trigger-cases.json +31 -0
- package/skills/qa-ui-automation/trigger-cases.json +31 -0
- package/skills/quant-analysis/trigger-cases.json +31 -0
- package/skills/rag-triage/SKILL.md +64 -0
- package/skills/rag-triage/evals.json +57 -0
- package/skills/rag-triage/references/triage-playbook.md +75 -0
- package/skills/rag-triage/trigger-cases.json +31 -0
- package/skills/real-estate-property/trigger-cases.json +30 -0
- package/skills/refactor-safely/SKILL.md +1 -1
- package/skills/refactor-safely/trigger-cases.json +30 -0
- package/skills/regression-forecast/trigger-cases.json +31 -0
- package/skills/release-checklist/trigger-cases.json +31 -0
- package/skills/report-craft/SKILL.md +76 -0
- package/skills/report-craft/references/feasibility.md +118 -0
- package/skills/report-craft/references/review-checklist.md +51 -0
- package/skills/report-craft/references/visuals.md +114 -0
- package/skills/report-craft/references/writing.md +80 -0
- package/skills/report-craft/scripts/__pycache__/chart_render.cpython-312.pyc +0 -0
- package/skills/report-craft/scripts/__pycache__/fin_model.cpython-312.pyc +0 -0
- package/skills/report-craft/scripts/__pycache__/project_facts.cpython-312.pyc +0 -0
- package/skills/report-craft/scripts/chart_render.py +1222 -0
- package/skills/report-craft/scripts/fin_model.py +602 -0
- package/skills/report-craft/scripts/project_facts.py +580 -0
- package/skills/report-craft/scripts/report_battery.py +349 -0
- package/skills/report-craft/trigger-cases.json +15 -0
- package/skills/retail-store-ops/trigger-cases.json +30 -0
- package/skills/risk-compliance/trigger-cases.json +31 -0
- package/skills/scope-creep/SKILL.md +45 -0
- package/skills/scope-creep/trigger-cases.json +7 -0
- package/skills/sec-auth/trigger-cases.json +31 -0
- package/skills/sec-compliance/trigger-cases.json +31 -0
- package/skills/securities-chain/trigger-cases.json +31 -0
- package/skills/securities-research/trigger-cases.json +31 -0
- package/skills/security-audit/trigger-cases.json +31 -0
- package/skills/slides-html/SKILL.md +25 -10
- package/skills/slides-html/trigger-cases.json +11 -0
- package/skills/sql-analysis/SKILL.md +110 -0
- package/skills/sql-analysis/trigger-cases.json +34 -0
- package/skills/sql-tuning/trigger-cases.json +31 -0
- package/skills/statistical-testing/trigger-cases.json +31 -0
- package/skills/strategy-planning/trigger-cases.json +30 -0
- package/skills/supply-chain/trigger-cases.json +31 -0
- package/skills/tax-compliance/trigger-cases.json +30 -0
- package/skills/tech-doc/SKILL.md +262 -0
- package/skills/tech-doc/scripts/__pycache__/archive_battery.cpython-312.pyc +0 -0
- package/skills/tech-doc/scripts/__pycache__/archive_build.cpython-312.pyc +0 -0
- package/skills/tech-doc/scripts/__pycache__/archive_check.cpython-312.pyc +0 -0
- package/skills/tech-doc/scripts/__pycache__/archive_spec.cpython-312.pyc +0 -0
- package/skills/tech-doc/scripts/__pycache__/doc_templates.cpython-312.pyc +0 -0
- package/skills/tech-doc/scripts/archive_battery.py +860 -0
- package/skills/tech-doc/scripts/archive_build.py +599 -0
- package/skills/tech-doc/scripts/archive_check.py +1307 -0
- package/skills/tech-doc/scripts/archive_spec.py +499 -0
- package/skills/tech-doc/scripts/doc_templates.py +624 -0
- package/skills/tech-doc/trigger-cases.json +57 -0
- package/skills/tech-research/trigger-cases.json +31 -0
- package/skills/tender-bidding/trigger-cases.json +31 -0
- package/skills/translation-pro/trigger-cases.json +30 -0
- package/skills/treasury-mgmt/trigger-cases.json +31 -0
- package/skills/trim-cot-leakage/SKILL.md +58 -0
- package/skills/trim-cot-leakage/trigger-cases.json +23 -0
- package/skills/web-craft/SKILL.md +103 -0
- package/skills/web-craft/references/craft-checklist.md +75 -0
- package/skills/web-craft/references/design-direction.md +122 -0
- package/skills/web-craft/references/h5-mobile.md +100 -0
- package/skills/web-craft/references/motion.md +136 -0
- package/skills/web-craft/references/recipes.md +74 -0
- package/skills/web-craft/templates/wedding-invitation.html +1180 -0
- package/skills/web-craft/trigger-cases.json +14 -0
- package/skills/web-scraping/trigger-cases.json +34 -0
- package/skills/web-search/SKILL.md +11 -10
- package/skills/web-search/trigger-cases.json +31 -0
- package/skills/weekly-report/SKILL.md +134 -0
- package/skills/weekly-report/trigger-cases.json +11 -0
- package/skills/write-tests/trigger-cases.json +31 -0
- package/skills/xlsx-analysis/SKILL.md +143 -77
- package/skills/xlsx-analysis/scripts/__pycache__/data_profile.cpython-312.pyc +0 -0
- package/skills/xlsx-analysis/scripts/__pycache__/xlsx_build.cpython-312.pyc +0 -0
- package/skills/xlsx-analysis/scripts/__pycache__/xlsx_check.cpython-312.pyc +0 -0
- package/skills/xlsx-analysis/scripts/__pycache__/xlsx_layout.cpython-312.pyc +0 -0
- package/skills/xlsx-analysis/scripts/__pycache__/xlsx_toolkit.cpython-312.pyc +0 -0
- package/skills/xlsx-analysis/scripts/data_profile.py +391 -0
- package/skills/xlsx-analysis/scripts/xlsx_battery.py +389 -0
- package/skills/xlsx-analysis/scripts/xlsx_build.py +522 -0
- package/skills/xlsx-analysis/scripts/xlsx_check.py +924 -0
- package/skills/xlsx-analysis/scripts/xlsx_layout.py +235 -0
- package/skills/xlsx-analysis/scripts/xlsx_style.py +28 -66
- package/skills/xlsx-analysis/scripts/xlsx_toolkit.py +61 -5
- package/skills/xlsx-analysis/trigger-cases.json +59 -0
- package/squads/hc-defense.md +47 -0
- package/squads/hc-rdarchive.md +110 -0
- package/squads/hc-redteam.md +50 -0
- package/squads/hc-weekly.md +125 -0
- package/src/account.js +1 -1
- package/src/acp.js +1 -0
- package/src/advisor.js +1 -1
- package/src/agent.js +1 -1
- package/src/api.js +1 -1
- package/src/archaeology.js +1 -0
- package/src/ask-ui.js +1 -0
- package/src/assets-import.js +1 -1
- package/src/autofix.js +1 -1
- package/src/automation-tools.js +1 -1
- package/src/automation.js +1 -1
- package/src/autorun.js +1 -1
- package/src/banner.js +1 -1
- package/src/capability-probe.js +1 -0
- package/src/checkpoints.js +1 -1
- package/src/code-tools.js +1 -0
- package/src/codeindex.js +1 -1
- package/src/codemode.js +1 -0
- package/src/command-bridge.js +1 -0
- package/src/command-ui.js +1 -0
- package/src/commands.js +1 -1
- package/src/compaction.js +1 -1
- package/src/computer.js +1 -1
- package/src/config.js +1 -1
- package/src/consult.js +1 -1
- package/src/context-report.js +1 -1
- package/src/context-window.js +1 -0
- package/src/context.js +1 -1
- package/src/crew.js +1 -0
- package/src/crush.js +1 -0
- package/src/daemon.js +1 -1
- package/src/decisions.js +1 -1
- package/src/depaudit.js +1 -0
- package/src/device.js +1 -1
- package/src/diagram-draw.js +1 -0
- package/src/diagram-layouts.js +1 -0
- package/src/diagram-raster.js +1 -0
- package/src/diagram.js +1 -0
- package/src/dictation.js +1 -0
- package/src/diffview.js +1 -1
- package/src/doctor.js +1 -1
- package/src/docx-tools.js +1 -0
- package/src/engineering.js +1 -0
- package/src/errkind.js +1 -1
- package/src/evidence.js +1 -0
- package/src/executors.js +1 -1
- package/src/expert-catalog.js +1 -1
- package/src/experts-store.js +1 -1
- package/src/experts.js +1 -1
- package/src/external-agents.js +1 -0
- package/src/forks.js +1 -1
- package/src/fs-observe.js +1 -0
- package/src/gitflow.js +1 -1
- package/src/goalround.js +1 -0
- package/src/hooks.js +1 -1
- package/src/ide.js +1 -1
- package/src/input.js +1 -1
- package/src/insights.js +1 -1
- package/src/jobs.js +1 -0
- package/src/kbsync.js +1 -1
- package/src/lsp.js +1 -0
- package/src/mcp-apps.js +1 -0
- package/src/mcp.js +1 -1
- package/src/memory.js +1 -1
- package/src/notify.js +1 -1
- package/src/permissions.js +1 -1
- package/src/plan-limits.js +1 -0
- package/src/policy.js +1 -0
- package/src/pptx-tools.js +1 -0
- package/src/presence.js +1 -1
- package/src/privatedir.js +1 -0
- package/src/pyruntime.js +1 -1
- package/src/radar.js +1 -0
- package/src/render.js +1 -1
- package/src/repl.js +1 -1
- package/src/report-tools.js +1 -0
- package/src/routing.js +1 -0
- package/src/sandbox-probe.js +1 -0
- package/src/sandbox-win-launcher.mjs +156 -0
- package/src/sandbox.js +1 -0
- package/src/scan.js +1 -1
- package/src/schedule.js +1 -1
- package/src/scopecreep.js +1 -0
- package/src/sdk.js +1 -0
- package/src/selection.js +1 -0
- package/src/session-events.js +1 -0
- package/src/session.js +1 -1
- package/src/sessionindex.js +1 -0
- package/src/sessionlog.js +1 -0
- package/src/skill-catalog.js +1 -0
- package/src/skill-lint.js +1 -0
- package/src/skill-optimize.js +1 -0
- package/src/skill-scan.js +1 -0
- package/src/skills.js +1 -1
- package/src/spill.js +1 -0
- package/src/squad.js +1 -1
- package/src/subagent.js +1 -1
- package/src/surface-state.js +1 -0
- package/src/tapd.js +1 -0
- package/src/terminal-select.js +1 -0
- package/src/terminal.js +1 -0
- package/src/test-runner.js +1 -0
- package/src/todo.js +1 -1
- package/src/toolpipe.js +1 -0
- package/src/tools.js +1 -1
- package/src/toon.js +1 -0
- package/src/transcript.js +1 -1
- package/src/tui/app.js +1 -1
- package/src/tui/command-menu.js +1 -0
- package/src/tui/progress.js +1 -0
- package/src/tui/scroll.js +1 -0
- package/src/tui/welcome.js +1 -0
- package/src/tui/workbench.js +1 -0
- package/src/ui-spec.js +1 -0
- package/src/uitree.js +1 -0
- package/src/uninstall.js +1 -1
- package/src/vision.js +1 -1
- package/src/visual.js +1 -1
- package/src/voice-form.js +1 -0
- package/src/voice.js +1 -0
- package/src/watch.js +1 -1
- package/src/web-audit.js +1 -0
- package/src/web-cdp.js +1 -0
- package/src/web-inspect.js +1 -0
- package/src/websearch.js +1 -0
- package/src/weekly.js +1 -0
- package/src/workflow.js +1 -0
- package/src/worklog.js +1 -0
- package/src/xlsx-tools.js +1 -0
- package/ui/command-picker.js +79 -0
- package/skills/ab-testing/scripts/__pycache__/ab_test.cpython-312.pyc +0 -0
- package/skills/accounting-ops/scripts/__pycache__/acct_tools.cpython-312.pyc +0 -0
- package/skills/anomaly-detection/scripts/__pycache__/anomaly.cpython-312.pyc +0 -0
- package/skills/audit-assist/scripts/__pycache__/audit_sampling.cpython-312.pyc +0 -0
- package/skills/banking-credit/scripts/__pycache__/credit_metrics.cpython-312.pyc +0 -0
- package/skills/data-report-pro/scripts/__pycache__/bigdata.cpython-312.pyc +0 -0
- package/skills/data-wrangling/scripts/__pycache__/join_tools.cpython-312.pyc +0 -0
- package/skills/ecommerce-ops/scripts/__pycache__/gmv_decompose.cpython-312.pyc +0 -0
- package/skills/funnel-cohort/scripts/__pycache__/funnel.cpython-312.pyc +0 -0
- package/skills/management-accounting/scripts/__pycache__/costing.cpython-312.pyc +0 -0
- package/skills/manufacturing-quality/scripts/__pycache__/spc.cpython-312.pyc +0 -0
- package/skills/marketing-analytics/scripts/__pycache__/rfm.cpython-312.pyc +0 -0
- package/skills/optimization-solver/scripts/__pycache__/solver.cpython-312.pyc +0 -0
- package/skills/pivot-crosstab/scripts/__pycache__/pivot_tools.cpython-312.pyc +0 -0
- package/skills/portfolio-analysis/scripts/__pycache__/portfolio.cpython-312.pyc +0 -0
- package/skills/procurement-supply/scripts/__pycache__/supply.cpython-312.pyc +0 -0
- package/skills/production-planning/scripts/__pycache__/mrp_capacity.cpython-312.pyc +0 -0
- package/skills/project-management/scripts/__pycache__/cpm.cpython-312.pyc +0 -0
- package/skills/quant-analysis/scripts/__pycache__/quant.cpython-312.pyc +0 -0
- package/skills/real-estate-property/scripts/__pycache__/property_calc.cpython-312.pyc +0 -0
- package/skills/regression-forecast/scripts/__pycache__/regress.cpython-312.pyc +0 -0
- package/skills/securities-research/scripts/__pycache__/valuation.cpython-312.pyc +0 -0
- package/skills/statistical-testing/scripts/__pycache__/stat_tests.cpython-312.pyc +0 -0
- package/skills/treasury-mgmt/scripts/__pycache__/cashflow_forecast.cpython-312.pyc +0 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# 报告引擎压测台:图表引擎 / 财务测算 / 项目事实清单。改了这三个脚本中任何一个,必须重跑。
|
|
3
|
+
#
|
|
4
|
+
# [1/3] 图表:每种图型 × 随机数据 N 份,断言出图成功、PNG 是按版心宽 300dpi 出的、
|
|
5
|
+
# 数值标注之间不重叠(逐个量文字框)、同一张图的标注小数位一致;
|
|
6
|
+
# 再加一组「必须拒绝」的输入(双纵轴、系列与类别数对不上、负值饼图、>8 个系列),断言报错而不是硬画。
|
|
7
|
+
# [2/3] 财务:教科书算例对答案;随机假设下的恒等式(IRR 处 NPV≈0、回收期落在累计由负转正的年份里、
|
|
8
|
+
# 节约额永不超过被节约的支出、税后 NPV ≤ 税前 NPV、敏感性临界点处 NPV≈0)。
|
|
9
|
+
# [3/3] 取证:合成代码库里埋一个口令,断言输出里一个字都不出;同步副本只算一次。
|
|
10
|
+
#
|
|
11
|
+
# 用法:python report_battery.py [份数] (出图部分需要 matplotlib:用托管运行时的 python 跑)
|
|
12
|
+
|
|
13
|
+
import json
|
|
14
|
+
import os
|
|
15
|
+
import random
|
|
16
|
+
import shutil
|
|
17
|
+
import sys
|
|
18
|
+
import tempfile
|
|
19
|
+
|
|
20
|
+
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
21
|
+
sys.path.insert(0, HERE)
|
|
22
|
+
|
|
23
|
+
import fin_model as F # noqa: E402
|
|
24
|
+
import project_facts as PF # noqa: E402
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
import chart_render as CR # noqa: E402
|
|
28
|
+
HAS_MPL = True
|
|
29
|
+
except Exception: # 系统 python 没装 matplotlib:图表段跳过并说明
|
|
30
|
+
HAS_MPL = False
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def rnd_series(rng, n_cat, n_s, lo=5, hi=900, neg=False):
|
|
34
|
+
return [{'name': f'系列{i + 1}', 'values': [round(rng.uniform(-hi / 3 if neg else lo, hi), rng.choice([0, 1, 2]))
|
|
35
|
+
for _ in range(n_cat)]} for i in range(n_s)]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def rnd_spec(rng, t):
|
|
39
|
+
n_cat = rng.randint(2, 9)
|
|
40
|
+
cats = [str(2026 + i) if rng.random() < 0.5 else rng.choice(['华东', '华南', '华北', '西南', '研发人员人工',
|
|
41
|
+
'算力与云资源', '测试', '推广', '预备费']) + str(i)
|
|
42
|
+
for i in range(n_cat)]
|
|
43
|
+
if t in ('bar', 'hbar'):
|
|
44
|
+
return {'type': t, 'unit': '万元', 'categories': cats, 'series': rnd_series(rng, n_cat, rng.randint(1, 3), neg=rng.random() < 0.2)}
|
|
45
|
+
if t in ('stacked', 'hstacked'):
|
|
46
|
+
return {'type': t, 'unit': '万元', 'categories': cats, 'series': rnd_series(rng, n_cat, rng.randint(2, 4))}
|
|
47
|
+
if t in ('line', 'area'):
|
|
48
|
+
return {'type': t, 'unit': '%', 'categories': cats, 'series': rnd_series(rng, n_cat, 1 if t == 'area' else rng.randint(1, 4), neg=True)}
|
|
49
|
+
if t == 'pie':
|
|
50
|
+
return {'type': 'pie', 'unit': '万元', 'categories': cats, 'series': rnd_series(rng, n_cat, 1)}
|
|
51
|
+
if t == 'waterfall':
|
|
52
|
+
return {'type': 'waterfall', 'unit': '万元', 'items': [{'name': c, 'value': round(rng.uniform(-80, 300), 1)} for c in cats]}
|
|
53
|
+
if t == 'tornado':
|
|
54
|
+
base = round(rng.uniform(100, 600), 2)
|
|
55
|
+
return {'type': 'tornado', 'unit': '万元', 'metric': 'NPV', 'base': base,
|
|
56
|
+
'items': [{'name': c, 'low': round(base - rng.uniform(5, 300), 2), 'high': round(base + rng.uniform(5, 300), 2),
|
|
57
|
+
'low_label': '-20%', 'high_label': '+20%'} for c in cats[:6]]}
|
|
58
|
+
if t == 'gantt':
|
|
59
|
+
tasks, m = [], rng.randint(1, 12)
|
|
60
|
+
for i in range(rng.randint(2, 9)):
|
|
61
|
+
s = m + rng.randint(0, 3)
|
|
62
|
+
e = s + rng.randint(0, 5)
|
|
63
|
+
tasks.append({'name': f'任务{i + 1}', 'start': f'{2026 + (s - 1) // 12}-{(s - 1) % 12 + 1:02d}',
|
|
64
|
+
'end': f'{2026 + (e - 1) // 12}-{(e - 1) % 12 + 1:02d}', 'group': f'阶段{i // 3 + 1}'})
|
|
65
|
+
m = s + 1
|
|
66
|
+
return {'type': 'gantt', 'tasks': tasks, 'today': '2026-09-23',
|
|
67
|
+
'milestones': [{'name': '验收', 'date': tasks[-1]['end'] + '-28'}]}
|
|
68
|
+
return {'type': 'matrix', 'items': [{'id': f'R{i + 1}', 'name': f'风险{i + 1}', 'p': rng.randint(1, 5), 'i': rng.randint(1, 5)}
|
|
69
|
+
for i in range(rng.randint(1, 9))]}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def label_boxes(fig):
|
|
73
|
+
"""图里所有数值标注(annotate 出的 Text)的像素框。"""
|
|
74
|
+
import matplotlib.text as mtext
|
|
75
|
+
r = fig.canvas.get_renderer()
|
|
76
|
+
boxes = []
|
|
77
|
+
for ax in fig.axes:
|
|
78
|
+
for ch in ax.get_children():
|
|
79
|
+
if isinstance(ch, mtext.Annotation) and ch.get_text().strip():
|
|
80
|
+
bb = ch.get_window_extent(renderer=r)
|
|
81
|
+
boxes.append((bb.x0, bb.y0, bb.x1, bb.y1, ch.get_text()))
|
|
82
|
+
return boxes
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def fig_text_boxes(fig):
|
|
86
|
+
"""画在 figure 上的文字(单位、图例、图下注)。"""
|
|
87
|
+
r = fig.canvas.get_renderer()
|
|
88
|
+
out = []
|
|
89
|
+
for t in fig.texts:
|
|
90
|
+
if t.get_text().strip():
|
|
91
|
+
bb = t.get_window_extent(renderer=r)
|
|
92
|
+
out.append((bb.x0, bb.y0, bb.x1, bb.y1, t.get_text()[:20]))
|
|
93
|
+
return out
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def overlaps(boxes):
|
|
97
|
+
bad = []
|
|
98
|
+
for i in range(len(boxes)):
|
|
99
|
+
for j in range(i + 1, len(boxes)):
|
|
100
|
+
a, b = boxes[i], boxes[j]
|
|
101
|
+
if a[0] < b[2] - 1 and b[0] < a[2] - 1 and a[1] < b[3] - 1 and b[1] < a[3] - 1:
|
|
102
|
+
bad.append((a[4], b[4]))
|
|
103
|
+
return bad
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# 真实翻车过的输入固定成回归用例(随机生成器造不出「里程碑扎堆 + 长任务名」这种组合)
|
|
107
|
+
REGRESSION = [
|
|
108
|
+
{'type': 'gantt', 'title': 'A/B 实施进度', 'today': '2026-09-01',
|
|
109
|
+
'tasks': [{'name': '试用问题修复与跨端一致性收敛', 'start': '2026-10', 'end': '2027-01', 'group': '完善收敛期'},
|
|
110
|
+
{'name': '支付与订阅闭环打通、会员正式收费', 'start': '2026-11', 'end': '2027-02', 'group': '完善收敛期'},
|
|
111
|
+
{'name': '私有化交付标准化与交付手册', 'start': '2026-12', 'end': '2027-03', 'group': '交付突破期'},
|
|
112
|
+
{'name': '规模化运营与产品迭代', 'start': '2027-07', 'end': '2031-12', 'group': '运营增长期'}],
|
|
113
|
+
'milestones': [{'name': '试用问题修复完成', 'date': '2027-01-31'}, {'name': '会员订阅正式收费', 'date': '2027-02-28'},
|
|
114
|
+
{'name': '私有化交付标准件发布', 'date': '2027-03-31'}, {'name': '首批私有化客户验收', 'date': '2027-06-30'},
|
|
115
|
+
{'name': '累计净现金流转正', 'date': '2030-12-31'}]},
|
|
116
|
+
{'type': 'gantt', 'title': '两个里程碑挨着', 'tasks': [{'name': '开发', 'start': '2026-10', 'end': '2027-03'}],
|
|
117
|
+
'milestones': [{'name': '方案评审通过', 'date': '2026-10-31'}, {'name': '原型演示', 'date': '2026-11-15'}]},
|
|
118
|
+
{'type': 'gantt', 'title': '五个分组(图例一行放不下)', 'today': '2026-09-23',
|
|
119
|
+
'tasks': [{'name': f'任务{i}', 'start': f'2026-{10 + i % 3:02d}', 'end': f'2027-{1 + i % 6:02d}',
|
|
120
|
+
'group': g} for i, g in enumerate(['产品能力', '交付能力', '安全合规', '商业化', '工程基础', '产品能力'])],
|
|
121
|
+
'milestones': [{'name': '首个私有化项目验收', 'date': '2027-01-31'}, {'name': '付费闭环正式上线', 'date': '2027-02-28'}]},
|
|
122
|
+
{'type': 'bar', 'unit': '万元', 'categories': ['2027', '2028'],
|
|
123
|
+
'series': [{'name': f'第{i}条业务线(含私有化交付)', 'values': [10 + i, 20 + i]} for i in range(8)], 'labels': 'none'},
|
|
124
|
+
{'type': 'gantt', 'title': '八个里程碑 + 图下注(图注不许被截断)', 'today': '2026-09-24',
|
|
125
|
+
'tasks': [{'name': '稳定性与性能收口', 'start': '2026-10', 'end': '2026-12'},
|
|
126
|
+
{'name': '商业运营与持续演进', 'start': '2027-10', 'end': '2031-09'}],
|
|
127
|
+
'milestones': [{'name': n, 'date': d} for n, d in [('压测基线达标', '2027-01-01'), ('交付包发布', '2027-03-01'),
|
|
128
|
+
('等保测评通过', '2027-05-01'), ('四端正式上架', '2027-08-01'), ('运营期启动', '2027-10-01'),
|
|
129
|
+
('首批私有化客户验收', '2027-11-15'), ('年度复盘与规划', '2027-12-20'), ('累计净现金流转正', '2030-06-30')]],
|
|
130
|
+
'note': '数据来源:项目进度计划(2026-09-24 编制),里程碑判定标准见表 6-2;运营期按 5 年计。'},
|
|
131
|
+
{'type': 'tornado', 'unit': '万元', 'metric': 'NPV', 'base': 518.77,
|
|
132
|
+
'items': [{'name': '经营成本', 'low': 862.78, 'high': 173.67, 'low_label': '-20%', 'high_label': '+20%'},
|
|
133
|
+
{'name': '营业收入', 'low': 274.09, 'high': 763.26, 'low_label': '-20%', 'high_label': '+20%'}]},
|
|
134
|
+
]
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def charts(n, work):
|
|
138
|
+
import matplotlib.pyplot as plt
|
|
139
|
+
rng = random.Random(7)
|
|
140
|
+
types = ['bar', 'hbar', 'stacked', 'hstacked', 'line', 'area', 'pie', 'waterfall', 'tornado', 'gantt', 'matrix']
|
|
141
|
+
fails = []
|
|
142
|
+
orig_close = plt.close
|
|
143
|
+
specs = [(types[k % len(types)], None) for k in range(n)] + [(r['type'], r) for r in REGRESSION]
|
|
144
|
+
for k, (t, fixed) in enumerate(specs):
|
|
145
|
+
spec = fixed or rnd_spec(rng, t)
|
|
146
|
+
out = os.path.join(work, f'c{k}.png')
|
|
147
|
+
captured = {}
|
|
148
|
+
plt.close = lambda fig=None: captured.setdefault('fig', fig) # 拦住关闭,留下 figure 量标注
|
|
149
|
+
try:
|
|
150
|
+
res = CR.render(spec, out)
|
|
151
|
+
except CR.SpecError as e:
|
|
152
|
+
fails.append((t, f'合法随机输入被拒:{e}', spec))
|
|
153
|
+
continue
|
|
154
|
+
except Exception as e:
|
|
155
|
+
fails.append((t, f'引擎异常:{type(e).__name__}: {e}', spec))
|
|
156
|
+
continue
|
|
157
|
+
finally:
|
|
158
|
+
plt.close = orig_close
|
|
159
|
+
fig = captured.get('fig')
|
|
160
|
+
from PIL import Image
|
|
161
|
+
with Image.open(out) as im:
|
|
162
|
+
w_px = im.size[0]
|
|
163
|
+
dpi = (im.info.get('dpi') or (0, 0))[0]
|
|
164
|
+
if abs(w_px - round(res['width_cm'] / 2.54 * 300)) > 2 or round(dpi) != 300:
|
|
165
|
+
fails.append((t, f'出图尺寸不对:{w_px}px @ {dpi}dpi', spec))
|
|
166
|
+
if not os.path.exists(os.path.splitext(out)[0] + '.svg'):
|
|
167
|
+
fails.append((t, '缺同名 SVG', spec))
|
|
168
|
+
if fig is not None and t not in ('pie', 'matrix'):
|
|
169
|
+
bad = overlaps(label_boxes(fig))
|
|
170
|
+
if bad:
|
|
171
|
+
fails.append((t, f'数值标注互相压住:{bad[:3]}', spec))
|
|
172
|
+
if fig is not None and t == 'gantt' and spec.get('milestones'):
|
|
173
|
+
shown = ''.join(b[4] for b in label_boxes(fig)) + ''.join(tx.get_text() for tx in fig.texts)
|
|
174
|
+
shown = shown.replace('\n', '')
|
|
175
|
+
lost = [m['name'] for m in spec['milestones'] if m['name'] not in shown]
|
|
176
|
+
if lost:
|
|
177
|
+
fails.append((t, f'里程碑在图上丢了(标注和图注里都找不到):{lost}', spec))
|
|
178
|
+
if fig is not None:
|
|
179
|
+
W, H = fig.bbox.width, fig.bbox.height
|
|
180
|
+
out_of = [b[4] for b in label_boxes(fig) + fig_text_boxes(fig) if b[0] < -1 or b[2] > W + 1 or b[1] < -1 or b[3] > H + 1]
|
|
181
|
+
if out_of:
|
|
182
|
+
fails.append((t, f'文字出了画布(会被裁掉):{out_of[:3]}', spec))
|
|
183
|
+
if t == 'tornado' and min(min(it['low'], it['high']) for it in spec['items']) >= 0:
|
|
184
|
+
ticks = [tk for tk in fig.axes[0].get_xticks()]
|
|
185
|
+
if any(tk < 0 for tk in ticks):
|
|
186
|
+
fails.append((t, f'数据全为正却标出负刻度:{ticks}', spec))
|
|
187
|
+
nums = [b[4].split('(')[0].replace(',', '').lstrip('+-') for b in label_boxes(fig)]
|
|
188
|
+
decs = {len(x.split('.')[1]) if '.' in x else 0 for x in nums if x.replace('.', '').isdigit()}
|
|
189
|
+
if len(decs) > 1:
|
|
190
|
+
fails.append((t, f'同一张图标注小数位不一致:{sorted(decs)}', spec))
|
|
191
|
+
if fig is not None:
|
|
192
|
+
orig_close(fig)
|
|
193
|
+
must_reject = [
|
|
194
|
+
({'type': 'line', 'y2': True, 'categories': ['a', 'b'], 'series': [{'name': 'x', 'values': [1, 2]}]}, '双纵轴'),
|
|
195
|
+
({'type': 'bar', 'categories': ['a', 'b'], 'series': [{'name': 'x', 'values': [1]}]}, '值与类别数不符'),
|
|
196
|
+
({'type': 'pie', 'categories': ['a', 'b'], 'series': [{'values': [3, -1]}]}, '负值饼图'),
|
|
197
|
+
({'type': 'bar', 'categories': ['a'], 'series': [{'name': str(i), 'values': [i]} for i in range(9)]}, '9 个系列'),
|
|
198
|
+
({'type': 'gantt', 'tasks': [{'name': 'x', 'start': '2027-05', 'end': '2027-01'}]}, '结束早于开始'),
|
|
199
|
+
({'type': 'matrix', 'items': [{'p': 6, 'i': 1}]}, '可能性超出 1~5'),
|
|
200
|
+
({'type': 'radar'}, '不认识的图型'),
|
|
201
|
+
]
|
|
202
|
+
rejected = 0
|
|
203
|
+
for spec, why in must_reject:
|
|
204
|
+
try:
|
|
205
|
+
CR.render(spec, os.path.join(work, 'x.png'))
|
|
206
|
+
fails.append(('reject', f'本该拒绝却画了:{why}', spec))
|
|
207
|
+
except CR.SpecError:
|
|
208
|
+
rejected += 1
|
|
209
|
+
return fails, rejected, len(must_reject)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def finance(n):
|
|
213
|
+
fails = []
|
|
214
|
+
# 教科书算例
|
|
215
|
+
r = F.run({'years': 5, 'discount_rate': 0.1, 'investment': [{'name': 'a', 'amount': 100}],
|
|
216
|
+
'revenue': [{'name': 'r', 'per_year': 30}], 'costs': [{'name': 'c', 'per_year': 0}]})
|
|
217
|
+
i = r['indicators']['pre_tax']
|
|
218
|
+
for k, v, want in (('npv', i['npv'], 12.476), ('irr', i['irr'], 0.152382), ('payback', i['payback'], 4.3333),
|
|
219
|
+
('payback_dynamic', i['payback_dynamic'], 5.2633)):
|
|
220
|
+
if abs(v - want) > 1e-3:
|
|
221
|
+
fails.append(('教科书', f'{k}={v} 期望 {want}'))
|
|
222
|
+
# 情景方向:实测模型给悲观情景设了「收入×0.6、成本×0.8」——必须预警;方向对的情景不能误报
|
|
223
|
+
base_spec = {'years': 5, 'investment': [{'name': 'a', 'amount': 400}],
|
|
224
|
+
'revenue': [{'name': 'r', 'values': [200, 300, 400, 500, 600]}],
|
|
225
|
+
'costs': [{'name': '上游', 'pct_of_revenue': 0.35}, {'name': '人力', 'per_year': 80}]}
|
|
226
|
+
w_bad = F.run({**base_spec, 'scenarios': {'悲观': {'revenue': 0.6, 'costs': 0.8}, '乐观': {'revenue': 1.3, 'costs': 1.1}}})['warnings']
|
|
227
|
+
w_ok = F.run({**base_spec, 'scenarios': {'悲观': {'revenue': 0.7, 'costs': 1.1}, '乐观': {'revenue': 1.2, 'costs': 0.95}}})['warnings']
|
|
228
|
+
if sum('方向不对' in w for w in w_bad) != 2:
|
|
229
|
+
fails.append(('情景方向', f'方向相反的悲观/乐观情景没被点名:{w_bad}'))
|
|
230
|
+
if any('方向不对' in w for w in w_ok):
|
|
231
|
+
fails.append(('情景方向', f'方向正确的情景被误报:{w_ok}'))
|
|
232
|
+
rng = random.Random(11)
|
|
233
|
+
for k in range(n):
|
|
234
|
+
years = rng.randint(3, 10)
|
|
235
|
+
m = rng.randint(1, 3)
|
|
236
|
+
inv = [{'name': f'投{j}', 'amount': rng.uniform(50, 800), 'schedule': None} for j in range(rng.randint(1, 5))]
|
|
237
|
+
for it in inv:
|
|
238
|
+
w = [rng.random() + 0.01 for _ in range(m)]
|
|
239
|
+
it['schedule'] = [x / sum(w) for x in w]
|
|
240
|
+
spec = {'years': years, 'construction_years': m, 'discount_rate': rng.choice([0.06, 0.08, 0.1, 0.12]),
|
|
241
|
+
'tax_rate': rng.choice([0, 0.15, 0.25]), 'investment': inv,
|
|
242
|
+
'revenue': [{'name': f'收{j}', 'values': [rng.uniform(0, 600) * (1 + t * 0.3) for t in range(years)]}
|
|
243
|
+
for j in range(rng.randint(1, 3))],
|
|
244
|
+
'costs': [{'name': '比例成本', 'pct_of_revenue': rng.uniform(0.05, 0.4)},
|
|
245
|
+
{'name': '固定成本', 'per_year': rng.uniform(10, 150), 'growth': rng.uniform(0, 0.1)}],
|
|
246
|
+
'savings': [{'name': '节约', 'base_values': [rng.uniform(5, 60) for _ in range(years)], 'rate': rng.uniform(0, 1)}],
|
|
247
|
+
'scenarios': {'悲观': {'revenue': 0.7, 'costs': 1.1}}}
|
|
248
|
+
try:
|
|
249
|
+
res = F.run(spec)
|
|
250
|
+
except F.ModelError as e:
|
|
251
|
+
fails.append((f'随机{k}', f'合法假设被拒:{e}'))
|
|
252
|
+
continue
|
|
253
|
+
M = F.load(spec)
|
|
254
|
+
cf = F.cashflows(M)
|
|
255
|
+
main = F.main_ncf(M, cf)
|
|
256
|
+
ii = F.indicators(main, M['r'])
|
|
257
|
+
if ii['irr'] is not None and abs(F.npv(main, ii['irr'])) > 1e-4 * max(1, sum(abs(x) for x in main)):
|
|
258
|
+
fails.append((f'随机{k}', f'IRR 处 NPV 不为 0:{F.npv(main, ii["irr"])}'))
|
|
259
|
+
for s in M['savings']:
|
|
260
|
+
if any(v > b + 1e-9 for v, b in zip(s['values'], s['base'])):
|
|
261
|
+
fails.append((f'随机{k}', '节约额超过了被节约的支出'))
|
|
262
|
+
if M['tax'] > 0 and F.npv(cf['post'], M['r']) > F.npv(cf['pre'], M['r']) + 1e-9:
|
|
263
|
+
fails.append((f'随机{k}', '税后 NPV 大于税前'))
|
|
264
|
+
pb = ii['payback']
|
|
265
|
+
if pb is not None:
|
|
266
|
+
cum, T = 0.0, None
|
|
267
|
+
for t, v in enumerate(main):
|
|
268
|
+
prev, cum = cum, cum + v
|
|
269
|
+
if t > 0 and prev < 0 <= cum:
|
|
270
|
+
T = t
|
|
271
|
+
break
|
|
272
|
+
# 年序从 1 起:第 T+1 年累计转正 → 回收期 = T + |上年累计| ÷ 当年净流入,落在 [T, T+1]
|
|
273
|
+
if T is None or not (T - 1e-9 <= pb <= T + 1 + 1e-9):
|
|
274
|
+
fails.append((f'随机{k}', f'回收期 {pb} 不在累计由负转正的那一年(T={T})'))
|
|
275
|
+
for srow in res['sensitivity']:
|
|
276
|
+
sw = srow['switch']
|
|
277
|
+
if sw is None or srow['factor'].startswith('其中'):
|
|
278
|
+
continue
|
|
279
|
+
key = {'营业收入': 'k_rev', '经营成本': 'k_cost', '建设投资': 'k_inv', '成本节约': 'k_sav'}[srow['factor']]
|
|
280
|
+
v = F.npv(F.main_ncf(M, F.cashflows(M, **{key: 1 + sw})), M['r'])
|
|
281
|
+
if abs(v) > 0.5: # switch 四舍五入到 4 位小数,留余量
|
|
282
|
+
fails.append((f'随机{k}', f'{srow["factor"]} 临界点处 NPV={v:.3f}'))
|
|
283
|
+
if not res['conclusion'] or '万元' not in res['conclusion']:
|
|
284
|
+
fails.append((f'随机{k}', '结论句缺失'))
|
|
285
|
+
return fails
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def facts(work):
|
|
289
|
+
fails = []
|
|
290
|
+
root = os.path.join(work, 'repo')
|
|
291
|
+
def w(p, s):
|
|
292
|
+
os.makedirs(os.path.dirname(os.path.join(root, p)), exist_ok=True)
|
|
293
|
+
open(os.path.join(root, p), 'w', encoding='utf-8').write(s)
|
|
294
|
+
w('svc/src/main/resources/application.yml',
|
|
295
|
+
'server:\n port: 9090\nspring:\n application:\n name: svc-a\n datasource:\n password: TopSecret#42\n'
|
|
296
|
+
' url: jdbc:mysql://10.0.0.8:3306/db?user=root&password=TopSecret#42\n')
|
|
297
|
+
w('svc/src/main/resources/application.properties', 'spring.datasource.password=PropSecret99\nserver.port=9091\n')
|
|
298
|
+
w('docker-compose.yml', 'services:\n db:\n image: mysql:8\n environment:\n MYSQL_ROOT_PASSWORD: ComposeSecret7\n ports:\n - "3306:3306"\n')
|
|
299
|
+
w('a/core/x.js', 'export const x = 1;\n' * 20)
|
|
300
|
+
w('b/core/x.js', 'export const x = 1;\n' * 20)
|
|
301
|
+
res = PF.build(root)
|
|
302
|
+
blob = json.dumps(res, ensure_ascii=False)
|
|
303
|
+
for secret in ('TopSecret#42', 'PropSecret99', 'ComposeSecret7', '10.0.0.8'):
|
|
304
|
+
if secret in blob:
|
|
305
|
+
fails.append(('取证', f'输出里出现了配置值:{secret}'))
|
|
306
|
+
if res['code']['duplicates']['files'] != 1:
|
|
307
|
+
fails.append(('取证', f'同步副本应计 1 个,实际 {res["code"]["duplicates"]["files"]}'))
|
|
308
|
+
if not any(s['name'] == 'svc-a' and s['port'] == '9090' for s in res['services']):
|
|
309
|
+
fails.append(('取证', f'没数出服务端口:{res["services"]}'))
|
|
310
|
+
if not any(sv['image'] == 'mysql:8' and sv['ports'] == ['3306:3306'] for c in res['compose'] for sv in c['services']):
|
|
311
|
+
fails.append(('取证', f'compose 服务没取对:{res["compose"]}'))
|
|
312
|
+
return fails
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def main(argv):
|
|
316
|
+
n = next((int(a) for a in argv if a.isdigit()), 120)
|
|
317
|
+
work = tempfile.mkdtemp(prefix='reportbat-')
|
|
318
|
+
bad = 0
|
|
319
|
+
try:
|
|
320
|
+
print(f'[1/3] 图表:{n} 份随机数据 × 11 种图型')
|
|
321
|
+
if HAS_MPL:
|
|
322
|
+
f, rej, tot = charts(n, work)
|
|
323
|
+
for t, why, spec in f[:10]:
|
|
324
|
+
print(f' ✗ {t}: {why}\n {json.dumps(spec, ensure_ascii=False)[:240]}')
|
|
325
|
+
print(f' {"✓" if not f else "✗"} {n + len(REGRESSION) - len([x for x in f if x[0] != "reject"])}/{n + len(REGRESSION)} 份出图合规'
|
|
326
|
+
f'(含 {len(REGRESSION)} 个真实翻车回归用例);必须拒绝的输入 {rej}/{tot} 被拒')
|
|
327
|
+
bad += bool(f)
|
|
328
|
+
else:
|
|
329
|
+
print(' - 跳过:当前 python 没有 matplotlib(用托管运行时的 python 跑这一段)')
|
|
330
|
+
print(f'[2/3] 财务:教科书算例 + {n} 组随机假设的恒等式')
|
|
331
|
+
f = finance(n)
|
|
332
|
+
for k, why in f[:10]:
|
|
333
|
+
print(f' ✗ {k}: {why}')
|
|
334
|
+
print(f' {"✓" if not f else "✗"} 全部恒等式成立' if not f else f' ✗ {len(f)} 处不成立')
|
|
335
|
+
bad += bool(f)
|
|
336
|
+
print('[3/3] 取证:埋了口令的合成代码库')
|
|
337
|
+
f = facts(work)
|
|
338
|
+
for k, why in f:
|
|
339
|
+
print(f' ✗ {k}: {why}')
|
|
340
|
+
print(' ✓ 配置值零泄露、同步副本只算一次、服务与编排取对' if not f else '')
|
|
341
|
+
bad += bool(f)
|
|
342
|
+
finally:
|
|
343
|
+
shutil.rmtree(work, ignore_errors=True)
|
|
344
|
+
print('\n全部通过。' if not bad else f'\n有 {bad} 段未通过。')
|
|
345
|
+
return 1 if bad else 0
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
if __name__ == '__main__':
|
|
349
|
+
sys.exit(main(sys.argv[1:]))
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "report-craft",
|
|
3
|
+
"cases": [
|
|
4
|
+
{ "id": "pos-finance", "prompt": "可研报告的财务评价怎么做,帮我算 NPV、IRR 和投资回收期", "shouldTrigger": true },
|
|
5
|
+
{ "id": "pos-sensitivity", "prompt": "项目报告里要有投资估算表、现金流量表,还要做敏感性分析", "shouldTrigger": true },
|
|
6
|
+
{ "id": "pos-charts", "prompt": "给这份报告配上甘特图、投资构成图和敏感性分析的龙卷风图", "shouldTrigger": true },
|
|
7
|
+
{ "id": "pos-facts", "prompt": "把代码库的规模、模块和接口数统计出来写进项目报告里", "shouldTrigger": true },
|
|
8
|
+
{ "id": "pos-bp", "prompt": "商业计划书的财务测算和数据图表怎么做才专业", "shouldTrigger": true },
|
|
9
|
+
{ "id": "pos-feasibility", "prompt": "编写我们项目的可行性研究报告,技术细节、架构图、功能模块图和各类图表都要专业", "shouldTrigger": true, "lexical": false },
|
|
10
|
+
{ "id": "neg-format", "prompt": "把这份 Word 的页边距和字体调成公文格式", "shouldTrigger": false },
|
|
11
|
+
{ "id": "neg-excel", "prompt": "分析一下这个 Excel 里的销售数据,做个透视表", "shouldTrigger": false },
|
|
12
|
+
{ "id": "neg-slides", "prompt": "做一份产品发布会用的 PPT", "shouldTrigger": false },
|
|
13
|
+
{ "id": "neg-weekly", "prompt": "帮我写本周的周报", "shouldTrigger": false }
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "retail-store-ops",
|
|
3
|
+
"cases": [
|
|
4
|
+
{
|
|
5
|
+
"id": "pos-1",
|
|
6
|
+
"prompt": "门店分析,坪效人效怎么算",
|
|
7
|
+
"shouldTrigger": true
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"id": "pos-2",
|
|
11
|
+
"prompt": "菜单工程和损耗盘点怎么做",
|
|
12
|
+
"shouldTrigger": true
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "pos-3",
|
|
16
|
+
"prompt": "选址评分和单店模型怎么建",
|
|
17
|
+
"shouldTrigger": true
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "neg-1",
|
|
21
|
+
"prompt": "做一次电商 GMV 的拆解归因",
|
|
22
|
+
"shouldTrigger": false
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"id": "neg-2",
|
|
26
|
+
"prompt": "写一份仓储 KPI 报表",
|
|
27
|
+
"shouldTrigger": false
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "risk-compliance",
|
|
3
|
+
"cases": [
|
|
4
|
+
{
|
|
5
|
+
"id": "pos-1",
|
|
6
|
+
"prompt": "做风险评估和风险登记册",
|
|
7
|
+
"shouldTrigger": true
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"id": "pos-2",
|
|
11
|
+
"prompt": "内控流程矩阵和合规检查怎么做",
|
|
12
|
+
"shouldTrigger": true
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "pos-3",
|
|
16
|
+
"prompt": "应急预案和数据合规要点",
|
|
17
|
+
"shouldTrigger": true
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "neg-1",
|
|
21
|
+
"prompt": "做一次内部审计项目立项",
|
|
22
|
+
"shouldTrigger": false,
|
|
23
|
+
"lexical": false
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "neg-2",
|
|
27
|
+
"prompt": "写一份等保测评整改方案",
|
|
28
|
+
"shouldTrigger": false
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: scope-creep
|
|
3
|
+
description: 变更范围蔓延检查——这次改动是不是跑题了:主要改动集中在哪个模块、哪些文件落在别处、是否顺手改了配置/构建文件、是否悄悄加了依赖、有没有巨型改动块或纯格式改动。当用户说"这次改了些什么/是不是改多了/提交前看一眼/帮我拆一下这次改动/范围是不是太大"时使用,长任务跑完后也应主动自查一次。
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 变更范围蔓延检查
|
|
8
|
+
|
|
9
|
+
一次改动最常见的失控形态不是「改错了」,而是**改多了**:跑一个长任务,回来发现顺手改了
|
|
10
|
+
八个无关文件。每一处单看都说得通,合在一起却成了一次没人能安心评审的提交——
|
|
11
|
+
评审的人只能整体通过或整体打回,而这两个选择都不对。
|
|
12
|
+
|
|
13
|
+
## 何时使用
|
|
14
|
+
|
|
15
|
+
- **长任务跑完之后主动自查**(这是最该用它的时刻,也是最容易忘的)
|
|
16
|
+
- 提交或开 PR 之前
|
|
17
|
+
- 用户问「这次改了些什么」「是不是改多了」「帮我拆一下」
|
|
18
|
+
|
|
19
|
+
## 怎么用
|
|
20
|
+
|
|
21
|
+
1. 调 `scope_check`。不传 intent 时会自动取当前目标(`/goal` 设过的那句话)作为意图。
|
|
22
|
+
2. 逐条回答它提的问题,然后二选一:
|
|
23
|
+
- **保留**:在提交信息里写清这个文件为什么必须一起改;
|
|
24
|
+
- **拆分**:`git restore --staged <文件>` 把它挪出本次提交,单独提一次。
|
|
25
|
+
3. 拆分优先。一次提交只做一件事,是让评审能进行下去的前提。
|
|
26
|
+
|
|
27
|
+
## 五类信号
|
|
28
|
+
|
|
29
|
+
| 信号 | 该问什么 |
|
|
30
|
+
|---|---|
|
|
31
|
+
| 落在主战场之外 | 这个文件是本次要做的事**必须**带上的吗? |
|
|
32
|
+
| 改到配置/构建文件 | 影响面远超它自身,且最容易在一堆功能改动里被漏看——确认必需,并在提交信息里单独点出来 |
|
|
33
|
+
| 依赖清单有新增 | 引入依赖是需要单独说明的决定(体积、许可证、维护状况、供应链风险),不该混在功能提交里 |
|
|
34
|
+
| 巨型改动块 | 这么大的块评审时几乎必然被囫囵放过。能拆就拆,拆不了就写清它做了什么 |
|
|
35
|
+
| 纯格式调整 | 单独提一次。混在功能改动里会让真正的改动淹没在一片重排里 |
|
|
36
|
+
|
|
37
|
+
## 边界
|
|
38
|
+
|
|
39
|
+
- **它只提问,不下结论。** 输出是「这几个文件看着不在主战场,是有意的吗」,
|
|
40
|
+
不是「这些文件是多余的」。很多跨模块改动本来就是必要的——一个接口改了,
|
|
41
|
+
上下游跟着改是应该的。判断该由人做。
|
|
42
|
+
- **不阻断提交。** 提交前只给提示。一个会拦住正当提交的检查器,两天之内就会被忽略。
|
|
43
|
+
- **改动少于四个文件时不查。** 那时谈不上「蔓延」,报告纯属噪声。
|
|
44
|
+
- **不审质量。** 代码写得对不对、有没有边界问题,那是 `code-review` 技能的事。
|
|
45
|
+
本技能只回答「该不该包含这些文件」。
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cases": [
|
|
3
|
+
{ "id": "changed-too-much", "prompt": "这次是不是改多了,帮我看看范围", "shouldTrigger": true },
|
|
4
|
+
{ "id": "split-change", "prompt": "提交前看一眼,帮我拆一下这次改动", "shouldTrigger": true },
|
|
5
|
+
{ "id": "review-quality", "prompt": "帮我审查这段代码的质量和边界情况", "shouldTrigger": false }
|
|
6
|
+
]
|
|
7
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "sec-auth",
|
|
3
|
+
"cases": [
|
|
4
|
+
{
|
|
5
|
+
"id": "pos-1",
|
|
6
|
+
"prompt": "接 SSO,OIDC 还是 SAML",
|
|
7
|
+
"shouldTrigger": true
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"id": "pos-2",
|
|
11
|
+
"prompt": "JWT 怎么吊销,会话还是 token",
|
|
12
|
+
"shouldTrigger": true
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "pos-3",
|
|
16
|
+
"prompt": "权限模型选 RBAC 还是 ABAC,越权怎么整改",
|
|
17
|
+
"shouldTrigger": true
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "neg-1",
|
|
21
|
+
"prompt": "做一次等保三级的合规整改",
|
|
22
|
+
"shouldTrigger": false,
|
|
23
|
+
"lexical": false
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "neg-2",
|
|
27
|
+
"prompt": "写一段接口签名的实现",
|
|
28
|
+
"shouldTrigger": false
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "sec-compliance",
|
|
3
|
+
"cases": [
|
|
4
|
+
{
|
|
5
|
+
"id": "pos-1",
|
|
6
|
+
"prompt": "等保测评临近,三级要求怎么落",
|
|
7
|
+
"shouldTrigger": true
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"id": "pos-2",
|
|
11
|
+
"prompt": "密评国密改造有哪些落点",
|
|
12
|
+
"shouldTrigger": true
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "pos-3",
|
|
16
|
+
"prompt": "客户问我们过等保没,开源 License 怎么合规",
|
|
17
|
+
"shouldTrigger": true
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "neg-1",
|
|
21
|
+
"prompt": "做一次 SSO 单点登录接入",
|
|
22
|
+
"shouldTrigger": false,
|
|
23
|
+
"lexical": false
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "neg-2",
|
|
27
|
+
"prompt": "写一份数据分级分类标准",
|
|
28
|
+
"shouldTrigger": false
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "securities-chain",
|
|
3
|
+
"cases": [
|
|
4
|
+
{
|
|
5
|
+
"id": "pos-1",
|
|
6
|
+
"prompt": "资本市场诉求跨环节,先看用哪个技能",
|
|
7
|
+
"shouldTrigger": true
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"id": "pos-2",
|
|
11
|
+
"prompt": "从辅导到上市,整条证券链怎么走",
|
|
12
|
+
"shouldTrigger": true
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "pos-3",
|
|
16
|
+
"prompt": "董秘全年披露怎么管,端到端排一下",
|
|
17
|
+
"shouldTrigger": true
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "neg-1",
|
|
21
|
+
"prompt": "做一次公司估值的 DCF 测算",
|
|
22
|
+
"shouldTrigger": false,
|
|
23
|
+
"lexical": false
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "neg-2",
|
|
27
|
+
"prompt": "写一份 IPO 申报材料清单",
|
|
28
|
+
"shouldTrigger": false
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "securities-research",
|
|
3
|
+
"cases": [
|
|
4
|
+
{
|
|
5
|
+
"id": "pos-1",
|
|
6
|
+
"prompt": "写份研报,公司研究框架怎么搭",
|
|
7
|
+
"shouldTrigger": true
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"id": "pos-2",
|
|
11
|
+
"prompt": "DCF 和可比估值怎么做",
|
|
12
|
+
"shouldTrigger": true
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "pos-3",
|
|
16
|
+
"prompt": "业绩点评和招股书分析怎么写",
|
|
17
|
+
"shouldTrigger": true
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "neg-1",
|
|
21
|
+
"prompt": "做一次持仓组合的再平衡",
|
|
22
|
+
"shouldTrigger": false,
|
|
23
|
+
"lexical": false
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "neg-2",
|
|
27
|
+
"prompt": "写一份上市申报的问询回复",
|
|
28
|
+
"shouldTrigger": false
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "security-audit",
|
|
3
|
+
"cases": [
|
|
4
|
+
{
|
|
5
|
+
"id": "pos-1",
|
|
6
|
+
"prompt": "帮我做代码安全自查",
|
|
7
|
+
"shouldTrigger": true
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"id": "pos-2",
|
|
11
|
+
"prompt": "这段代码安全吗,OWASP 风险有哪些",
|
|
12
|
+
"shouldTrigger": true
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "pos-3",
|
|
16
|
+
"prompt": "上线安全检查,鉴权和密钥怎么看",
|
|
17
|
+
"shouldTrigger": true
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "neg-1",
|
|
21
|
+
"prompt": "做一次安全评审的威胁建模",
|
|
22
|
+
"shouldTrigger": false,
|
|
23
|
+
"lexical": false
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "neg-2",
|
|
27
|
+
"prompt": "写一份等保测评证据清单",
|
|
28
|
+
"shouldTrigger": false
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|