minimal-agent 0.8.2 → 0.10.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/README.md +14 -12
- package/package.json +34 -1
- package/plugins/cron-runner/.claude-plugin/plugin.json +5 -0
- package/plugins/cron-runner/commands/cron.md +26 -0
- package/plugins/cron-runner/commands/crons.md +7 -0
- package/plugins/cron-runner/plugin.js +34 -0
- package/plugins/cron-runner/src/commands.js +348 -0
- package/plugins/cron-runner/src/cronTime.js +148 -0
- package/plugins/cron-runner/src/lock.js +68 -0
- package/plugins/cron-runner/src/runs.js +89 -0
- package/plugins/cron-runner/src/scheduleEngine.js +72 -0
- package/plugins/cron-runner/src/scheduler.js +355 -0
- package/plugins/cron-runner/src/schema.js +140 -0
- package/plugins/cron-runner/src/service.js +167 -0
- package/plugins/cron-runner/src/store.js +298 -0
- package/plugins/cron-runner/src/types.js +1 -0
- package/plugins/workflow-runner/commands/workflow.md +4 -4
- package/plugins/workflow-runner/commands/workflows.md +1 -1
- package/plugins/workflow-runner/plugin.js +3 -1
- package/plugins/workflow-runner/src/agentCommon.js +249 -51
- package/plugins/workflow-runner/src/dslManifest.js +72 -0
- package/plugins/workflow-runner/src/expressions.js +198 -15
- package/plugins/workflow-runner/src/index.js +40 -8
- package/plugins/workflow-runner/src/jsonPayload.js +1 -1
- package/plugins/workflow-runner/src/loader.js +286 -72
- package/plugins/workflow-runner/src/multimodal.js +37 -0
- package/plugins/workflow-runner/src/recovery.js +49 -39
- package/plugins/workflow-runner/src/runner.js +802 -287
- package/plugins/workflow-runner/src/stepExecutors/agent.js +157 -39
- package/plugins/workflow-runner/src/stepExecutors/assert.js +16 -3
- package/plugins/workflow-runner/src/stepExecutors/llm.js +60 -111
- package/plugins/workflow-runner/src/stepExecutors/skill.js +47 -47
- package/plugins/workflow-runner/src/stepExecutors/tool.js +76 -10
- package/plugins/workflow-runner/src/stepExecutors/verify.js +27 -10
- package/plugins/workflow-runner/src/taskIdentity.js +296 -0
- package/plugins/workflow-runner/src/types.js +19 -9
- package/plugins/workflow-runner/src/workflowState.js +516 -33
- package/skills/adversarial-review/SKILL.md +0 -1
- package/skills/ai-image/SKILL.md +89 -0
- package/skills/ai-image/scripts/generate.mjs +497 -0
- package/skills/ai-image/scripts/generate_from_plan.mjs +469 -0
- package/skills/ai-image/scripts/generate_from_plan_test.mjs +223 -0
- package/skills/ai-image/scripts/generate_test.mjs +74 -0
- package/skills/browser-automation/SKILL.md +47 -0
- package/skills/docx/SKILL.md +25 -3
- package/skills/docx/scripts/office/helpers/__pycache__/__init__.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/helpers/__pycache__/merge_runs.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/helpers/__pycache__/simplify_redlines.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/__init__.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/base.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/docx.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/pptx.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/redlining.cpython-314.pyc +0 -0
- package/skills/docx/scripts/opc_check.py +253 -0
- package/skills/image-gen-openrouter/SKILL.md +10 -2
- package/skills/image-stats/SKILL.md +65 -0
- package/skills/image-stats/scripts/__pycache__/image_stats.cpython-314.pyc +0 -0
- package/skills/image-stats/scripts/__pycache__/image_stats_test.cpython-314.pyc +0 -0
- package/skills/image-stats/scripts/image_stats.py +368 -0
- package/skills/image-stats/scripts/image_stats_test.py +181 -0
- package/skills/pptx/SKILL.md +123 -95
- package/skills/pptx/design.md +82 -0
- package/skills/pptx/examples/README.md +29 -0
- package/skills/pptx/examples/hybrid_example.mjs +107 -0
- package/skills/pptx/examples/hybrid_example.pptx +0 -0
- package/skills/pptx/pptxgenjs.md +41 -0
- package/skills/pptx/scripts/deck_helpers.mjs +224 -0
- package/skills/pptx/scripts/layout_lint.py +293 -0
- package/skills/pptx/scripts/layout_lint_test.py +160 -0
- package/skills/pptx/scripts/opc_check.py +339 -0
- package/skills/pptx/scripts/svg_fallback.mjs +145 -0
- package/skills/pptx/svg.md +67 -0
- package/skills/tts-zh/SKILL.md +19 -2
- package/skills/ui-design/SKILL.md +158 -0
- package/skills/ui-design/claude_design.md +309 -0
- package/skills/ui-design/evals/evals.json +254 -0
- package/skills/ui-design/references/aesthetic-direction.md +83 -0
- package/skills/ui-design/references/claude-design-protocol.md +36 -0
- package/skills/ui-design/references/design-context.md +53 -0
- package/skills/ui-design/references/design-execution-playbook.md +82 -0
- package/skills/ui-design/references/export-pptx.md +124 -0
- package/skills/ui-design/references/layout-composition.md +654 -0
- package/skills/ui-design/references/preview-feedback.md +37 -0
- package/skills/ui-design/references/source-image-layout.md +189 -0
- package/skills/ui-design/references/starter-components.md +78 -0
- package/skills/ui-design/references/vi-aegis-vector.md +144 -0
- package/skills/ui-design/references/vi-amber-prism.md +133 -0
- package/skills/ui-design/references/vi-aqua-glass.md +200 -0
- package/skills/ui-design/references/vi-comfort-vision.md +147 -0
- package/skills/ui-design/references/vi-ember-prism.md +140 -0
- package/skills/ui-design/references/vi-nebula-console.md +151 -0
- package/skills/ui-design/references/vi-obsidian-optics.md +139 -0
- package/skills/ui-design/references/vi-obsidian-xui.md +143 -0
- package/skills/ui-design/references/vi-precision-horizon-dark.md +117 -0
- package/skills/ui-design/references/vi-precision-horizon.md +215 -0
- package/skills/ui-design/references/vi-solar-relay.md +130 -0
- package/skills/ui-design/references/vi-template-workflow.md +48 -0
- package/skills/ui-design/references/vi-verdant-grid.md +141 -0
- package/skills/ui-design/references/vi-violet-meridian.md +172 -0
- package/skills/ui-design/scripts/__pycache__/assemble_material.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/assemble_material_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/chart_sanity_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/check_language_policy.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/check_ui_artifact.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/check_ui_artifact_pptx_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/deck_pages_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/deck_pages_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/deck_visual_style_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/deck_visual_style_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_budget_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_budget_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_repair_hints.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_repair_hints_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_style_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_style_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/draft_coverage_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/extract_source_assets.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/extract_source_assets_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/generated_image_review_collect.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/generated_image_review_collect_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/image_plan_lint.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/image_plan_lint_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/layout_balance.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/layout_balance_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/normalize_design_json.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/normalize_design_json_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/plan_source_layout.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/plan_source_layout_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/resolve_source_hint.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/resolve_source_hint_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/resolve_source_input.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/resolve_source_input_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/scaffold_ui_artifact.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/source_usage_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/source_usage_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/text_readability_pixel.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/visual_quality_gate.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/visual_quality_gate_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/assemble_material.py +217 -0
- package/skills/ui-design/scripts/assemble_material_test.py +149 -0
- package/skills/ui-design/scripts/browser_check_ui_artifact.mjs +221 -0
- package/skills/ui-design/scripts/chart_sanity_check.py +261 -0
- package/skills/ui-design/scripts/chart_sanity_check_test.py +165 -0
- package/skills/ui-design/scripts/check_language_policy.py +351 -0
- package/skills/ui-design/scripts/check_ui_artifact.py +435 -0
- package/skills/ui-design/scripts/check_ui_artifact_pptx_test.py +251 -0
- package/skills/ui-design/scripts/deck_pages_check.py +158 -0
- package/skills/ui-design/scripts/deck_pages_check_test.py +134 -0
- package/skills/ui-design/scripts/deck_visual_style_check.py +767 -0
- package/skills/ui-design/scripts/deck_visual_style_check_test.py +713 -0
- package/skills/ui-design/scripts/design_budget_check.py +271 -0
- package/skills/ui-design/scripts/design_budget_check_test.py +183 -0
- package/skills/ui-design/scripts/design_repair_hints.py +162 -0
- package/skills/ui-design/scripts/design_repair_hints_test.py +54 -0
- package/skills/ui-design/scripts/design_style_check.py +397 -0
- package/skills/ui-design/scripts/design_style_check_test.py +233 -0
- package/skills/ui-design/scripts/draft_coverage_check.py +184 -0
- package/skills/ui-design/scripts/draft_coverage_check_test.py +131 -0
- package/skills/ui-design/scripts/export_pptx_from_html.mjs +2367 -0
- package/skills/ui-design/scripts/extract_source_assets.py +607 -0
- package/skills/ui-design/scripts/extract_source_assets_test.py +256 -0
- package/skills/ui-design/scripts/generated_image_review_collect.py +206 -0
- package/skills/ui-design/scripts/generated_image_review_collect_test.py +91 -0
- package/skills/ui-design/scripts/image_plan_lint.py +571 -0
- package/skills/ui-design/scripts/image_plan_lint_test.py +515 -0
- package/skills/ui-design/scripts/image_prompt_rewrite.py +713 -0
- package/skills/ui-design/scripts/image_prompt_rewrite_test.py +966 -0
- package/skills/ui-design/scripts/layout_balance.py +881 -0
- package/skills/ui-design/scripts/layout_balance_test.py +927 -0
- package/skills/ui-design/scripts/normalize_design_json.py +272 -0
- package/skills/ui-design/scripts/normalize_design_json_test.py +119 -0
- package/skills/ui-design/scripts/plan_source_layout.py +1450 -0
- package/skills/ui-design/scripts/plan_source_layout_test.py +1136 -0
- package/skills/ui-design/scripts/resolve_source_input.py +270 -0
- package/skills/ui-design/scripts/resolve_source_input_test.py +98 -0
- package/skills/ui-design/scripts/scaffold_ui_artifact.py +377 -0
- package/skills/ui-design/scripts/source_usage_check.py +581 -0
- package/skills/ui-design/scripts/source_usage_check_test.py +427 -0
- package/skills/ui-design/scripts/text_readability_pixel.py +340 -0
- package/skills/ui-design/scripts/text_readability_pixel_test.py +219 -0
- package/skills/ui-design/scripts/visual_quality_gate.py +301 -0
- package/skills/ui-design/scripts/visual_quality_gate_test.py +233 -0
- package/skills/ui-design/tests/e2e/prompts/deck.md +19 -0
- package/skills/ui-design/tests/e2e/prompts/webpage.md +17 -0
- package/skills/ui-design/tests/e2e/render_check.mjs +101 -0
- package/skills/ui-design/tests/e2e/rubric.json +54 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/checks/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/checks/language-check.txt +12 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/checks/static-check.txt +15 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/outputs/index.html +837 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/prompt.md +12 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/review.md +21 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/outputs/homepage.html +373 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/outputs/platform.html +378 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/prompt.md +13 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/review.md +26 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/homepage/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/homepage/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/homepage/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/platform/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/platform/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/platform/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/outputs/index.html +656 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/prompt.md +12 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/render_check.mjs +67 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/outputs/index.html +587 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/prompt.md +12 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/review.md +36 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/checks/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/checks/language-check.txt +8 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/checks/static-check.txt +16 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/outputs/index.html +739 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/prompt.md +11 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/review.md +22 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/checks/browser-check.json +52 -0
- package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/outputs/index.html +641 -0
- package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/outputs/index.html +467 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/screenshots/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/outputs/homepage.html +373 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/outputs/platform.html +378 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/prompt.md +13 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/review.md +26 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/homepage/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/homepage/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/homepage/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/platform/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/platform/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/platform/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/checks/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/checks/language-check.txt +4 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/execution_notes.md +10 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/outputs/index.html +587 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/prompt.md +14 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/review.md +13 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/checks/browser-check.json +24 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/execution_notes.md +21 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/outputs/deck.html +451 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/screenshots/slide-01.png +0 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/screenshots/slide-02.png +0 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/review.md +79 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/checks/browser-check.json +26 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/execution_notes.md +20 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/outputs/index.html +534 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/browser-check.json +64 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/language-check.txt +7 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/quick-validate.txt +1 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/static-console.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/static-homepage.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/outputs/console.html +600 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/outputs/homepage.html +556 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/prompt.md +29 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/review.md +57 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/console-desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/console-mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/homepage-desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/homepage-mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/browser-check.json +33 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/language-check.txt +6 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/quick-validate.txt +1 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/outputs/index.html +682 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/prompt.md +13 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/review.md +59 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/outputs/page-01.html +466 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/outputs/page-02.html +433 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/prompt.md +13 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-01/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-01/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-01/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-02/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-02/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-02/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/checks/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/checks/language-check.txt +3 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/execution_notes.md +24 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/outputs/index.html +723 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/prompt.md +15 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/review.md +26 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/browser-dark.json +49 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/browser-light.json +49 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/language-check.txt +11 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/static-dark.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/static-light.txt +3 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/execution_notes.md +23 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/outputs/dark.html +392 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/outputs/light.html +476 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/prompt.md +23 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/review.md +41 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/dark/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/dark/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/light/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/light/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/browser-check.json +54 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/language-check.txt +5 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/quick-validate.txt +1 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/outputs/index.html +765 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/prompt.md +15 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/review.md +59 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/outputs/index.html +508 -0
- package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/screenshots/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/browser-check.json +54 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/language-check.txt +6 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/quick-validate.txt +1 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/outputs/index.html +788 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/prompt.md +14 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/review.md +60 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/screenshots/mobile.png +0 -0
- package/skills/video-compose/SKILL.md +8 -1
- package/skills/web-crawler/SKILL.md +70 -0
- package/skills/web-crawler/scripts/crawl.mjs +538 -0
- package/skills/web-crawler/scripts/crawl.test.mjs +204 -0
- package/skills/xlsx/SKILL.md +12 -0
- package/skills/xlsx/scripts/opc_check.py +253 -0
- package/src/advisorState.js +22 -0
- package/src/askBridge.js +97 -3
- package/src/bootstrap/workingDir.js +12 -1
- package/src/cli/args.js +17 -1
- package/src/cli/configMenu.js +236 -0
- package/src/cli/configWizard.js +7 -5
- package/src/cli/print.js +37 -4
- package/src/cli/streamJson.js +77 -24
- package/src/cli/wizards/advisorWizard.js +147 -0
- package/src/cli/wizards/fieldForm.js +149 -0
- package/src/cli/wizards/imageWizard.js +60 -0
- package/src/cli/wizards/openRouterWizard.js +23 -0
- package/src/cli/wizards/providerPresets.js +95 -0
- package/src/cli/wizards/providerWizard.js +219 -0
- package/src/cli/wizards/searchWizard.js +23 -0
- package/src/cli/wizards/ttsWizard.js +34 -0
- package/src/config/configFile.js +441 -83
- package/src/config/configService.js +446 -0
- package/src/config.js +24 -64
- package/src/context/agentHome.js +9 -0
- package/src/context/archive.js +7 -2
- package/src/context/compact.js +8 -5
- package/src/context/contextLock.js +81 -0
- package/src/context/persistContext.js +30 -11
- package/src/context/reactiveCompact.js +4 -2
- package/src/context/recentDirs.js +21 -61
- package/src/context/sessionPath.js +97 -23
- package/src/context/sessionRegistry.js +303 -24
- package/src/context/tokenCounter.js +18 -0
- package/src/context/workspaceIndex.js +731 -0
- package/src/infra/verification.js +28 -15
- package/src/llm/client.js +394 -159
- package/src/llm/providers/anthropicFormat.js +241 -0
- package/src/llm/providers/openaiFormat.js +190 -0
- package/src/loop.js +219 -32
- package/src/main.js +61 -11
- package/src/messageQueue.js +97 -0
- package/src/multimodal.js +203 -0
- package/src/plugin-sdk.js +15 -0
- package/src/plugins/commandRouter.js +3 -0
- package/src/plugins/hookEngine.js +5 -1
- package/src/plugins/pluginLifecycle.js +28 -0
- package/src/plugins/pluginLoader.js +2 -1
- package/src/plugins/pluginRunner.js +49 -21
- package/src/plugins/transcript.js +4 -3
- package/src/prompts/pluginList.js +5 -5
- package/src/prompts/projectInstructions.js +3 -3
- package/src/prompts/promptAssembly.js +133 -144
- package/src/prompts/skillList.js +12 -22
- package/src/prompts/system.js +0 -1
- package/src/session/runAgentTurn.js +70 -0
- package/src/session/runTurn.js +41 -6
- package/src/toolGate.js +17 -0
- package/src/tools/advisor/advisor.js +379 -0
- package/src/tools/agent/agent.js +555 -0
- package/src/tools/agent/agentTypes.js +59 -0
- package/src/tools/agent/coordinator.js +93 -0
- package/src/tools/agent/worktree.js +270 -0
- package/src/tools/ask/ask.js +7 -2
- package/src/tools/bash/bash.js +112 -18
- package/src/tools/download/download.js +144 -0
- package/src/tools/edit/edit.js +1 -0
- package/src/tools/edit/multi-edit.js +1 -0
- package/src/tools/genimage/genimage.js +242 -0
- package/src/tools/genspeech/genspeech.js +67 -0
- package/src/tools/glob/glob.js +1 -0
- package/src/tools/grep/grep.js +3 -0
- package/src/tools/grep/rgPath.js +2 -0
- package/src/tools/index.js +25 -2
- package/src/tools/read/read.js +1 -0
- package/src/tools/shared/killTree.js +52 -0
- package/src/tools/toolProgressBridge.js +48 -0
- package/src/tools/webbrowser/agentBrowserPath.js +258 -0
- package/src/tools/webbrowser/browser.js +59 -42
- package/src/tools/webbrowser/browserControl.js +118 -0
- package/src/tools/webbrowser/browserDaemon.js +97 -0
- package/src/tools/webbrowser/browserService.js +27 -0
- package/src/tools/webbrowser/browserStream.js +119 -0
- package/src/tools/webbrowser/webbrowser.js +699 -130
- package/src/tools/webfetch/webfetch.js +1 -0
- package/src/tools/websearch/websearch.js +134 -51
- package/src/tools/write/write.js +1 -0
- package/src/ui/App.js +249 -22
- package/src/ui/AskQuestion.js +29 -10
- package/src/ui/InputBox.js +104 -12
- package/src/ui/LiveArea.js +112 -19
- package/src/ui/MessageList.js +100 -14
- package/src/ui/ModelPicker.js +56 -0
- package/src/ui/QueuedMessagesBanner.js +14 -0
- package/src/ui/Root.js +18 -10
- package/src/ui/SessionPicker.js +102 -0
- package/src/ui/StatusLine.js +13 -4
- package/src/ui/WorkspacePicker.js +55 -0
- package/src/ui/figures.js +44 -0
- package/src/ui/hooks/askSlot.js +82 -0
- package/src/ui/hooks/useChat.js +358 -64
- package/src/ui/hooks/usePasteHandler.js +11 -1
- package/src/ui/hooks/useTextBuffer.js +1 -3
- package/src/ui/liveViewport.js +5 -1
- package/src/ui/markdown.js +206 -0
- package/src/ui/textBuffer.js +0 -7
- package/src/ui/theme.js +32 -0
- package/src/utils/debugLog.js +0 -4
- package/src/utils/resourcePaths.js +2 -2
- package/src/utils/stripThink.js +50 -0
- package/src/web/browserBridge.js +447 -0
- package/src/web/protocol.js +19 -0
- package/workflows/adaptive-research.yaml +13 -5
- package/workflows/book-review-short.yaml +36 -10
- package/workflows/e2e-write-greet.yaml +6 -2
- package/workflows/illustrate.yaml +227 -0
- package/workflows/plan.yaml +460 -179
- package/workflows/ppt.yaml +1659 -0
- package/workflows/ralph-loop.yaml +199 -0
- package/workflows/schema.json +81 -23
- package/workflows/webppt.yaml +496 -0
- package/workflows/word.yaml +710 -0
- package/workflows/youtube-shorts.yaml +46 -15
- package/MINIMAL-TRACE.md +0 -77
- package/plugins/HOW-TO-WRITE-A-PLUGIN.md +0 -186
- package/plugins/ralph-wiggum/.claude-plugin/plugin.json +0 -9
- package/plugins/ralph-wiggum/README.md +0 -197
- package/plugins/ralph-wiggum/commands/cancel-ralph.md +0 -18
- package/plugins/ralph-wiggum/commands/help.md +0 -137
- package/plugins/ralph-wiggum/commands/ralph-loop.md +0 -85
- package/plugins/ralph-wiggum/hooks/hooks.json +0 -15
- package/plugins/ralph-wiggum/hooks/stop-hook.sh +0 -191
- package/plugins/ralph-wiggum/plugin.js +0 -280
- package/plugins/ralph-wiggum/src/goalState.js +0 -258
- package/plugins/ralph-wiggum/src/sentinels.js +0 -76
- package/plugins/ralph-wiggum/src/stopHookRunner.js +0 -104
- package/plugins/ralph-wiggum/src/verificationGate.js +0 -202
- package/plugins/workflow-runner/src/miniReAct.js +0 -223
- package/plugins/workflow-runner/src/voteHelpers.js +0 -110
- package/skills/config/SKILL.md +0 -123
- package/skills/frontend-design/LICENSE.txt +0 -177
- package/skills/frontend-design/SKILL.md +0 -42
- package/src/ui/ProgressPanel.js +0 -54
- package/src/ui/StreamingBlock.js +0 -11
- package/src/ui/ToolStatus.js +0 -11
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
image_plan_lint_test.py —— image_plan_lint.py 的回归锚(stdlib unittest,仿 layout_balance_test 风格)。
|
|
5
|
+
|
|
6
|
+
夹具取自真机 build_bak(自包含、不依赖 build_bak 目录存在):
|
|
7
|
+
- 结构图(架构/并轨/决策树)必 FAIL;氛围/隐喻(封面渐变/山峰)必 PASS —— 反向校准锁死。
|
|
8
|
+
- 装饰/设计词(visual hierarchy / contrast / neural network nodes / layers of light / geometric)不误伤。
|
|
9
|
+
- 改写措辞规避("five stacked horizontal bands")lint 抓不到 —— 锁死「诚实边界」(那层靠 guidance)。
|
|
10
|
+
- 缺 img_plan.json = PASS(exit 0);含违规 = exit 1;干净 = exit 0(子进程验退出码)。
|
|
11
|
+
|
|
12
|
+
运行:python skills/ui-design/scripts/image_plan_lint_test.py
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import json
|
|
16
|
+
import os
|
|
17
|
+
import subprocess
|
|
18
|
+
import sys
|
|
19
|
+
import tempfile
|
|
20
|
+
import unittest
|
|
21
|
+
|
|
22
|
+
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
23
|
+
sys.path.insert(0, HERE)
|
|
24
|
+
from image_plan_lint import _find_bad_aesthetic_terms, _find_i2i_only_terms, _find_terms, lint # noqa: E402
|
|
25
|
+
from image_plan_lint import _find_background_text_marker_terms # noqa: E402
|
|
26
|
+
|
|
27
|
+
SCRIPT = os.path.join(HERE, "image_plan_lint.py")
|
|
28
|
+
|
|
29
|
+
# —— 真机 build_bak 的代表性 prompt(结构图 vs 氛围/隐喻)——
|
|
30
|
+
PROMPT_ARCH = ("Abstract technology architecture visualization with 5 distinct horizontal "
|
|
31
|
+
"layers representing data flow, clean minimalist lines")
|
|
32
|
+
PROMPT_TRACKS = ("Dual parallel evolution paths abstract visualization, two separate tracks "
|
|
33
|
+
"running in parallel representing commercial and open source")
|
|
34
|
+
PROMPT_TREE = ("Abstract decision tree visualization for technology selection guide, "
|
|
35
|
+
"three branching paths")
|
|
36
|
+
PROMPT_COVER = ("A clean modern abstract technology background, soft violet and blue gradient "
|
|
37
|
+
"light beams with subtle neural network nodes and connection lines, negative space")
|
|
38
|
+
PROMPT_MOUNTAIN = ("Abstract mountain climbing concept, four stylized mountain peaks, violet blue "
|
|
39
|
+
"cyan gradient, clean geometric lines with subtle glow")
|
|
40
|
+
# 改写措辞规避结构(无图表名词)—— 已知 lint 抓不到,靠 guidance。
|
|
41
|
+
PROMPT_PARAPHRASE = ("five stacked horizontal bands of soft light, each band a different hue, "
|
|
42
|
+
"minimalist, lots of negative space")
|
|
43
|
+
PROMPT_BAD_AESTHETIC = (
|
|
44
|
+
"abstract blueprint background with crosshair, aegis shield symbol, "
|
|
45
|
+
"18 thumbnails, floating cards and UI cards"
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def write_json(obj):
|
|
50
|
+
fd, path = tempfile.mkstemp(suffix=".json")
|
|
51
|
+
os.close(fd)
|
|
52
|
+
with open(path, "w", encoding="utf-8") as f:
|
|
53
|
+
json.dump(obj, f, ensure_ascii=False)
|
|
54
|
+
return path
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def plan(*prompts):
|
|
58
|
+
return [{"file": f"img_{i+1}.png", "aspect": "16:9", "prompt": p} for i, p in enumerate(prompts)]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def outline(*notes):
|
|
62
|
+
"""notes = [(route, note), ...] → 一个 outline.json。"""
|
|
63
|
+
return {"pages": [
|
|
64
|
+
{"page": i + 1, "title": f"页{i+1}", "visual": {"route": r, "note": n}}
|
|
65
|
+
for i, (r, n) in enumerate(notes)
|
|
66
|
+
]}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def run(img_plan_path, outline_path=None):
|
|
70
|
+
cmd = [sys.executable, SCRIPT, img_plan_path]
|
|
71
|
+
if outline_path:
|
|
72
|
+
cmd += ["--outline", outline_path]
|
|
73
|
+
r = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8")
|
|
74
|
+
return r.returncode, (r.stdout or "") + (r.stderr or "")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class FindTermsTest(unittest.TestCase):
|
|
78
|
+
def test_structural_prompts_hit(self):
|
|
79
|
+
self.assertTrue(_find_terms(PROMPT_ARCH)) # architecture / layered structure / data flow
|
|
80
|
+
self.assertTrue(_find_terms(PROMPT_TRACKS)) # parallel evolution
|
|
81
|
+
self.assertTrue(_find_terms(PROMPT_TREE)) # decision tree
|
|
82
|
+
|
|
83
|
+
def test_atmospheric_prompts_pass(self):
|
|
84
|
+
self.assertEqual(_find_terms(PROMPT_COVER), []) # 渐变 + 装饰节点 ≠ 结构图
|
|
85
|
+
self.assertEqual(_find_terms(PROMPT_MOUNTAIN), []) # 山峰隐喻 + geometric lines ≠ 结构图
|
|
86
|
+
|
|
87
|
+
def test_decorative_design_words_not_overblocked(self):
|
|
88
|
+
# 这些词在合法氛围图里常见,绝不能误伤:
|
|
89
|
+
for s in [
|
|
90
|
+
"strong visual hierarchy and depth", # 不收裸 hierarchy
|
|
91
|
+
"violet and blue contrast, 对比色", # 不收裸 contrast / 对比
|
|
92
|
+
"subtle neural network nodes", # 不收裸 network / nodes
|
|
93
|
+
"soft layers of light and mist", # 不收裸 layers / 分层
|
|
94
|
+
"clean geometric lines, glow", # 不收 geometric
|
|
95
|
+
]:
|
|
96
|
+
self.assertEqual(_find_terms(s), [], f"误伤装饰词:{s}")
|
|
97
|
+
|
|
98
|
+
def test_chinese_note_terms(self):
|
|
99
|
+
self.assertTrue(_find_terms("抽象的五层架构分层示意图背景")) # 架构
|
|
100
|
+
self.assertTrue(_find_terms("双轨演进的抽象概念背景")) # 双轨
|
|
101
|
+
self.assertTrue(_find_terms("技术选型决策树的抽象概念背景")) # 决策树
|
|
102
|
+
self.assertEqual(_find_terms("山峰与攀登意象的氛围背景"), []) # 隐喻放行
|
|
103
|
+
self.assertEqual(_find_terms("神经网络与幻灯片融合的全幅背景"), []) # 装饰放行
|
|
104
|
+
|
|
105
|
+
def test_paraphrase_evasion_is_known_gap(self):
|
|
106
|
+
# 诚实边界:改写措辞规避结构词,lint 抓不到(锁死此已知缺口,避免误以为全覆盖)。
|
|
107
|
+
self.assertEqual(_find_terms(PROMPT_PARAPHRASE), [])
|
|
108
|
+
|
|
109
|
+
def test_bad_aesthetic_terms_hit(self):
|
|
110
|
+
hits = _find_bad_aesthetic_terms(PROMPT_BAD_AESTHETIC)
|
|
111
|
+
self.assertIn("abstract blueprint", hits)
|
|
112
|
+
self.assertIn("crosshair", hits)
|
|
113
|
+
self.assertIn("aegis", hits)
|
|
114
|
+
self.assertIn("shield", hits)
|
|
115
|
+
self.assertIn("18 thumbnails", hits)
|
|
116
|
+
self.assertIn("floating cards", hits)
|
|
117
|
+
|
|
118
|
+
def test_negative_aesthetic_terms_do_not_hit(self):
|
|
119
|
+
self.assertEqual(
|
|
120
|
+
_find_bad_aesthetic_terms("clean product scene, do not create a collage or thumbnail grid"),
|
|
121
|
+
[],
|
|
122
|
+
)
|
|
123
|
+
self.assertEqual(
|
|
124
|
+
_find_bad_aesthetic_terms("cinematic background without floating cards or UI cards"),
|
|
125
|
+
[],
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
def test_i2i_only_terms_hit(self):
|
|
129
|
+
hits = _find_i2i_only_terms(
|
|
130
|
+
"Use the attached image as the strict visual reference and preserve its main subject."
|
|
131
|
+
)
|
|
132
|
+
self.assertIn("use the attached image", hits)
|
|
133
|
+
self.assertIn("strict visual reference", hits)
|
|
134
|
+
self.assertIn("preserve its main subject", hits)
|
|
135
|
+
|
|
136
|
+
def test_background_text_marker_terms_hit(self):
|
|
137
|
+
hits = _find_background_text_marker_terms("light route background with chapter numbers 1 2 3 4")
|
|
138
|
+
self.assertIn("chapter numbers", hits)
|
|
139
|
+
hits_cn = _find_background_text_marker_terms("背景里画四个章节序号和文字标签")
|
|
140
|
+
self.assertIn("章节序号", hits_cn)
|
|
141
|
+
|
|
142
|
+
def test_negative_background_text_marker_terms_do_not_hit(self):
|
|
143
|
+
self.assertEqual(_find_background_text_marker_terms("clean background with no chapter numbers"), [])
|
|
144
|
+
self.assertEqual(_find_background_text_marker_terms("背景禁止章节序号和文字标签"), [])
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class SlideCopyInBackgroundTest(unittest.TestCase):
|
|
148
|
+
"""slide_copy 背景检查(2026-07-03 ai_p9 事故):背景 t2i prompt 携带页标题/正文/图表描述 → 违规;
|
|
149
|
+
前景模板的 Topic anchors 合法;i2i 一律豁免;负面清单(no charts/no tables)不误伤。"""
|
|
150
|
+
|
|
151
|
+
OLD_AI_P9_PROMPT = (
|
|
152
|
+
"low-interference data-space background. Slide title: 投入有限,对冲无限. "
|
|
153
|
+
"Core message: 核心总投入约 3 万元. Topic anchors: 投入有限, 万元. "
|
|
154
|
+
"Visual focus: 成本拆解 HTML 表 + 投入/对冲对比柱状图. no text, no logo."
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
def _lint_items(self, items):
|
|
158
|
+
p = write_json(items)
|
|
159
|
+
try:
|
|
160
|
+
return lint(p)[0]
|
|
161
|
+
finally:
|
|
162
|
+
os.remove(p)
|
|
163
|
+
|
|
164
|
+
def test_old_ai_p9_background_prompt_flagged(self):
|
|
165
|
+
violations = self._lint_items(
|
|
166
|
+
[{"file": "ai_p9.png", "aspect": "16:9", "target_layer": "background",
|
|
167
|
+
"prompt": self.OLD_AI_P9_PROMPT}]
|
|
168
|
+
)
|
|
169
|
+
hit = [v for v in violations if "slide title:" in v.get("terms", []) or "柱状图" in v.get("terms", [])]
|
|
170
|
+
self.assertTrue(hit, violations)
|
|
171
|
+
|
|
172
|
+
def test_foreground_topic_anchors_not_flagged(self):
|
|
173
|
+
violations = self._lint_items(
|
|
174
|
+
[{"file": "ai_p3_fg.png", "aspect": "1:1", "role": "foreground",
|
|
175
|
+
"prompt": "single complete product cutout. Topic anchors: 全景相机, 装配现场. no text, no logo."}]
|
|
176
|
+
)
|
|
177
|
+
self.assertEqual([v for v in violations if v.get("hint", "").startswith("背景生图提示词")], [], violations)
|
|
178
|
+
|
|
179
|
+
def test_i2i_exempt(self):
|
|
180
|
+
violations = self._lint_items(
|
|
181
|
+
[{"file": "enhanced_src_6.png", "mode": "image-to-image", "aspect": "16:9",
|
|
182
|
+
"prompt": self.OLD_AI_P9_PROMPT}]
|
|
183
|
+
)
|
|
184
|
+
self.assertEqual(violations, [], violations)
|
|
185
|
+
|
|
186
|
+
def test_negated_chart_terms_do_not_hit(self):
|
|
187
|
+
violations = self._lint_items(
|
|
188
|
+
[{"file": "ai_p2.png", "aspect": "16:9", "target_layer": "background",
|
|
189
|
+
"prompt": "clean industrial atmosphere, absolutely no text, no charts, no tables, "
|
|
190
|
+
"no diagrams, no slide-like layout, no logo."}]
|
|
191
|
+
)
|
|
192
|
+
self.assertEqual(violations, [], violations)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class LintTest(unittest.TestCase):
|
|
196
|
+
def test_build_bak_separation(self):
|
|
197
|
+
"""img_2/3/5 结构图 FAIL,img_1/4 氛围 PASS(精确到 file)。"""
|
|
198
|
+
p = write_json(plan(PROMPT_COVER, PROMPT_ARCH, PROMPT_TRACKS, PROMPT_MOUNTAIN, PROMPT_TREE))
|
|
199
|
+
try:
|
|
200
|
+
violations, scanned, exists = lint(p)
|
|
201
|
+
self.assertTrue(exists)
|
|
202
|
+
self.assertEqual(scanned, 5)
|
|
203
|
+
flagged = {v["id"] for v in violations}
|
|
204
|
+
self.assertEqual(flagged, {"img_2.png", "img_3.png", "img_5.png"})
|
|
205
|
+
finally:
|
|
206
|
+
os.remove(p)
|
|
207
|
+
|
|
208
|
+
def test_outline_note_pass_catches_via_route(self):
|
|
209
|
+
"""只扫 route=ai-A/ai-B(AI 凭空生成)的 note;source-enhanced(客户图 img2img)与 html 均豁免。
|
|
210
|
+
|
|
211
|
+
注:page 4「把客户截图增强成流程图背景」曾被断言要命中("source-enhanced 也不能承载结构"),
|
|
212
|
+
但那是误伤——img2img 保原图内容,note 只是描述文字,实际产物是被保留的客户图;拦它只会逼「删
|
|
213
|
+
img_plan / 改 HTML」丢弃真实客户图。本用例已纠正为**放行 source-enhanced**(客户真图非 AI 凭空造)。
|
|
214
|
+
"""
|
|
215
|
+
p = write_json(plan(PROMPT_COVER)) # img_plan 干净
|
|
216
|
+
o = write_json(outline(
|
|
217
|
+
("ai-B", "封面渐变氛围"), # 干净
|
|
218
|
+
("ai-A", "抽象的五层架构分层示意图背景"), # 架构 → 命中(ai-A 凭空生成)
|
|
219
|
+
("source-enhanced", "客户图扩展为干净产品背景"), # 客户图 → 豁免
|
|
220
|
+
("source-enhanced", "把客户截图增强成流程图背景"), # 客户图(img2img 保原图)→ 豁免,不再误伤
|
|
221
|
+
("html", "用 HTML 画流程图对比"), # html 路由,不扫
|
|
222
|
+
))
|
|
223
|
+
try:
|
|
224
|
+
violations, scanned, _ = lint(p, o)
|
|
225
|
+
ids = {v["id"] for v in violations}
|
|
226
|
+
self.assertTrue(any("page 2" in i for i in ids)) # 仅 ai-A 凭空生结构 → 命中
|
|
227
|
+
self.assertFalse(any("page 3" in i for i in ids)) # source-enhanced 客户图豁免
|
|
228
|
+
self.assertFalse(any("page 4" in i for i in ids)) # source-enhanced 客户图豁免(曾误命中,本次纠正)
|
|
229
|
+
self.assertFalse(any("page 5" in i for i in ids)) # html 页不扫
|
|
230
|
+
finally:
|
|
231
|
+
os.remove(p)
|
|
232
|
+
os.remove(o)
|
|
233
|
+
|
|
234
|
+
def test_source_enhanced_structural_note_not_flagged(self):
|
|
235
|
+
# 真机复现:客户图 src_6 是「信息密集对比图」,route=source-enhanced、direct_contain 原比例。
|
|
236
|
+
# 曾被结构词「对比图」误判 FAILED → 整条 ppt 工作流 halt。修后放行(客户真图,非 AI 凭空生成)。
|
|
237
|
+
p = write_json(plan(PROMPT_COVER)) # img_plan 干净
|
|
238
|
+
o = write_json(outline(
|
|
239
|
+
("source-enhanced", "src_6 信息密集对比图(传统多球机九宫格 vs 全景相机+AI 检测),direct_contain 原比例"),
|
|
240
|
+
))
|
|
241
|
+
try:
|
|
242
|
+
code, out = run(p, o)
|
|
243
|
+
self.assertEqual(code, 0, out)
|
|
244
|
+
self.assertIn("PASSED", out)
|
|
245
|
+
finally:
|
|
246
|
+
os.remove(p)
|
|
247
|
+
os.remove(o)
|
|
248
|
+
|
|
249
|
+
def test_image_to_image_structural_prompt_not_flagged(self):
|
|
250
|
+
# img2img 增强客户图:prompt 描述真图内容含结构词(comparison chart)→ 豁免(真图非 AI 造结构)。
|
|
251
|
+
# 对照 test_violation_exit1(text-to-image 结构 → 仍命中 exit 1):只放宽 image-to-image。
|
|
252
|
+
p = write_json([
|
|
253
|
+
{
|
|
254
|
+
"file": "enhanced_src_6.png",
|
|
255
|
+
"mode": "image-to-image",
|
|
256
|
+
"source_file": "src_6.png",
|
|
257
|
+
"aspect": "16:9",
|
|
258
|
+
"prompt": "Enhance the attached comparison chart, preserve its main subject, content and real colors.",
|
|
259
|
+
}
|
|
260
|
+
])
|
|
261
|
+
try:
|
|
262
|
+
code, out = run(p)
|
|
263
|
+
self.assertEqual(code, 0, out)
|
|
264
|
+
self.assertIn("PASSED", out)
|
|
265
|
+
finally:
|
|
266
|
+
os.remove(p)
|
|
267
|
+
|
|
268
|
+
def test_missing_img_plan_passes(self):
|
|
269
|
+
code, out = run(os.path.join(tempfile.gettempdir(), "no_such_img_plan_xyz.json"))
|
|
270
|
+
self.assertEqual(code, 0)
|
|
271
|
+
self.assertIn("PASSED", out)
|
|
272
|
+
|
|
273
|
+
def test_clean_plan_exit0(self):
|
|
274
|
+
p = write_json(plan(PROMPT_COVER, PROMPT_MOUNTAIN))
|
|
275
|
+
try:
|
|
276
|
+
code, out = run(p)
|
|
277
|
+
self.assertEqual(code, 0)
|
|
278
|
+
self.assertIn("PASSED", out)
|
|
279
|
+
finally:
|
|
280
|
+
os.remove(p)
|
|
281
|
+
|
|
282
|
+
def test_directory_mode_prefers_design_json_before_outline_json(self):
|
|
283
|
+
with tempfile.TemporaryDirectory() as d:
|
|
284
|
+
img_plan = os.path.join(d, "img_plan.json")
|
|
285
|
+
design_path = os.path.join(d, "design.json")
|
|
286
|
+
outline_path = os.path.join(d, "outline.json")
|
|
287
|
+
with open(img_plan, "w", encoding="utf-8") as f:
|
|
288
|
+
json.dump(plan(PROMPT_COVER), f, ensure_ascii=False)
|
|
289
|
+
with open(design_path, "w", encoding="utf-8") as f:
|
|
290
|
+
json.dump(outline(("ai-A", "抽象的五层架构分层示意图背景")), f, ensure_ascii=False)
|
|
291
|
+
with open(outline_path, "w", encoding="utf-8") as f:
|
|
292
|
+
json.dump(outline(("ai-A", "封面渐变氛围")), f, ensure_ascii=False)
|
|
293
|
+
|
|
294
|
+
code, out = run(d)
|
|
295
|
+
self.assertEqual(code, 1)
|
|
296
|
+
self.assertIn("page 1", out)
|
|
297
|
+
self.assertIn("架构", out)
|
|
298
|
+
|
|
299
|
+
def test_violation_exit1(self):
|
|
300
|
+
p = write_json(plan(PROMPT_ARCH))
|
|
301
|
+
try:
|
|
302
|
+
code, out = run(p)
|
|
303
|
+
self.assertEqual(code, 1)
|
|
304
|
+
self.assertIn("FAILED", out)
|
|
305
|
+
self.assertIn("img_1.png", out)
|
|
306
|
+
finally:
|
|
307
|
+
os.remove(p)
|
|
308
|
+
|
|
309
|
+
def test_bad_aesthetic_prompt_exit1(self):
|
|
310
|
+
p = write_json(plan(PROMPT_BAD_AESTHETIC))
|
|
311
|
+
try:
|
|
312
|
+
code, out = run(p)
|
|
313
|
+
self.assertEqual(code, 1)
|
|
314
|
+
self.assertIn("FAILED", out)
|
|
315
|
+
self.assertIn("摄影感场景", out)
|
|
316
|
+
finally:
|
|
317
|
+
os.remove(p)
|
|
318
|
+
|
|
319
|
+
def test_text_to_image_cannot_use_i2i_prompt(self):
|
|
320
|
+
p = write_json([
|
|
321
|
+
{
|
|
322
|
+
"file": "ai_p9.png",
|
|
323
|
+
"mode": "text-to-image",
|
|
324
|
+
"aspect": "16:9",
|
|
325
|
+
"prompt": "Use the attached image as the strict visual reference: preserve its main subject.",
|
|
326
|
+
}
|
|
327
|
+
])
|
|
328
|
+
try:
|
|
329
|
+
code, out = run(p)
|
|
330
|
+
self.assertEqual(code, 1)
|
|
331
|
+
self.assertIn("图生图提示词", out)
|
|
332
|
+
self.assertIn("ai_p9.png", out)
|
|
333
|
+
finally:
|
|
334
|
+
os.remove(p)
|
|
335
|
+
|
|
336
|
+
def test_text_to_image_cannot_generate_chapter_numbers(self):
|
|
337
|
+
p = write_json([
|
|
338
|
+
{
|
|
339
|
+
"file": "ai_p2.png",
|
|
340
|
+
"mode": "text-to-image",
|
|
341
|
+
"aspect": "16:9",
|
|
342
|
+
"prompt": "light blue industrial background with chapter numbers 1 2 3 4",
|
|
343
|
+
}
|
|
344
|
+
])
|
|
345
|
+
try:
|
|
346
|
+
code, out = run(p)
|
|
347
|
+
self.assertEqual(code, 1)
|
|
348
|
+
self.assertIn("章节序号", out)
|
|
349
|
+
self.assertIn("不可编辑文字", out)
|
|
350
|
+
finally:
|
|
351
|
+
os.remove(p)
|
|
352
|
+
|
|
353
|
+
def test_text_to_image_negative_chapter_numbers_pass(self):
|
|
354
|
+
p = write_json([
|
|
355
|
+
{
|
|
356
|
+
"file": "ai_p2.png",
|
|
357
|
+
"mode": "text-to-image",
|
|
358
|
+
"aspect": "16:9",
|
|
359
|
+
"prompt": "clean route background with no chapter numbers and no text labels",
|
|
360
|
+
}
|
|
361
|
+
])
|
|
362
|
+
try:
|
|
363
|
+
code, out = run(p)
|
|
364
|
+
self.assertEqual(code, 0, out)
|
|
365
|
+
finally:
|
|
366
|
+
os.remove(p)
|
|
367
|
+
|
|
368
|
+
def test_image_to_image_allows_i2i_prompt(self):
|
|
369
|
+
p = write_json([
|
|
370
|
+
{
|
|
371
|
+
"file": "enhanced_src_1.png",
|
|
372
|
+
"mode": "image-to-image",
|
|
373
|
+
"source_file": "src_1.png",
|
|
374
|
+
"aspect": "16:9",
|
|
375
|
+
"prompt": "Use the attached image as the strict visual reference: preserve its main subject.",
|
|
376
|
+
}
|
|
377
|
+
])
|
|
378
|
+
try:
|
|
379
|
+
code, out = run(p)
|
|
380
|
+
self.assertEqual(code, 0, out)
|
|
381
|
+
self.assertIn("PASSED", out)
|
|
382
|
+
finally:
|
|
383
|
+
os.remove(p)
|
|
384
|
+
|
|
385
|
+
def test_generic_product_prompt_without_domain_anchor_fails(self):
|
|
386
|
+
p = write_json([
|
|
387
|
+
{
|
|
388
|
+
"file": "ai_p11.png",
|
|
389
|
+
"mode": "text-to-image",
|
|
390
|
+
"aspect": "16:9",
|
|
391
|
+
"prompt": "professional product photography of a sleek device on a dark premium background",
|
|
392
|
+
}
|
|
393
|
+
])
|
|
394
|
+
try:
|
|
395
|
+
code, out = run(p)
|
|
396
|
+
self.assertEqual(code, 1)
|
|
397
|
+
self.assertIn("随机消费品", out)
|
|
398
|
+
self.assertIn("ai_p11.png", out)
|
|
399
|
+
finally:
|
|
400
|
+
os.remove(p)
|
|
401
|
+
|
|
402
|
+
def test_negative_random_object_constraints_pass(self):
|
|
403
|
+
p = write_json([
|
|
404
|
+
{
|
|
405
|
+
"file": "ai_p11.png",
|
|
406
|
+
"mode": "text-to-image",
|
|
407
|
+
"aspect": "16:9",
|
|
408
|
+
"prompt": "energy grid inspection scene, no game controller, no cosmetic bottle, no random monitor, no text",
|
|
409
|
+
}
|
|
410
|
+
])
|
|
411
|
+
o = write_json({
|
|
412
|
+
"pages": [
|
|
413
|
+
{"page": 11, "title": "能源电网巡检", "visual_focus": "energy grid inspection scene"}
|
|
414
|
+
]
|
|
415
|
+
})
|
|
416
|
+
try:
|
|
417
|
+
code, out = run(p, o)
|
|
418
|
+
self.assertEqual(code, 0, out)
|
|
419
|
+
finally:
|
|
420
|
+
os.remove(p)
|
|
421
|
+
os.remove(o)
|
|
422
|
+
|
|
423
|
+
def test_domain_bound_product_prompt_passes(self):
|
|
424
|
+
p = write_json([
|
|
425
|
+
{
|
|
426
|
+
"file": "ai_p11.png",
|
|
427
|
+
"mode": "text-to-image",
|
|
428
|
+
"aspect": "16:9",
|
|
429
|
+
"prompt": (
|
|
430
|
+
"professional product photography of an energy grid inspection robot "
|
|
431
|
+
"inside a substation operations room, no text, no logo"
|
|
432
|
+
),
|
|
433
|
+
}
|
|
434
|
+
])
|
|
435
|
+
o = write_json({
|
|
436
|
+
"pages": [
|
|
437
|
+
{
|
|
438
|
+
"page": 11,
|
|
439
|
+
"title": "能源电网巡检机器人",
|
|
440
|
+
"one_sentence_takeaway": "变电站巡检机器人把现场状态同步给调度中心。",
|
|
441
|
+
"visual_focus": "energy grid inspection robot inside a substation operations room",
|
|
442
|
+
"visual": {"route": "ai-B", "note": "能源电网巡检机器人"},
|
|
443
|
+
}
|
|
444
|
+
]
|
|
445
|
+
})
|
|
446
|
+
try:
|
|
447
|
+
code, out = run(p, o)
|
|
448
|
+
self.assertEqual(code, 0, out)
|
|
449
|
+
finally:
|
|
450
|
+
os.remove(p)
|
|
451
|
+
os.remove(o)
|
|
452
|
+
|
|
453
|
+
def test_non_aviation_domain_bound_prompts_pass(self):
|
|
454
|
+
p = write_json([
|
|
455
|
+
{
|
|
456
|
+
"file": "ai_p3.png",
|
|
457
|
+
"mode": "text-to-image",
|
|
458
|
+
"aspect": "16:9",
|
|
459
|
+
"prompt": "professional product photography of a medical imaging diagnostic workstation in a hospital reading room, no text, no logo",
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
"file": "ai_p4.png",
|
|
463
|
+
"mode": "text-to-image",
|
|
464
|
+
"aspect": "16:9",
|
|
465
|
+
"prompt": "professional product photography of a foldable phone hinge closeup for premium consumer hardware, no text, no logo",
|
|
466
|
+
},
|
|
467
|
+
])
|
|
468
|
+
o = write_json({
|
|
469
|
+
"pages": [
|
|
470
|
+
{"page": 3, "title": "医疗影像诊断工作站", "visual_focus": "medical imaging diagnostic workstation hospital reading room"},
|
|
471
|
+
{"page": 4, "title": "消费硬件折叠铰链", "visual_focus": "foldable phone hinge closeup premium consumer hardware"},
|
|
472
|
+
]
|
|
473
|
+
})
|
|
474
|
+
try:
|
|
475
|
+
code, out = run(p, o)
|
|
476
|
+
self.assertEqual(code, 0, out)
|
|
477
|
+
finally:
|
|
478
|
+
os.remove(p)
|
|
479
|
+
os.remove(o)
|
|
480
|
+
|
|
481
|
+
def test_explicit_unrelated_object_fails_even_with_other_words(self):
|
|
482
|
+
p = write_json([
|
|
483
|
+
{
|
|
484
|
+
"file": "ai_p7.png",
|
|
485
|
+
"mode": "text-to-image",
|
|
486
|
+
"aspect": "16:9",
|
|
487
|
+
"prompt": "energy grid operations background with a game controller in the center",
|
|
488
|
+
}
|
|
489
|
+
])
|
|
490
|
+
try:
|
|
491
|
+
code, out = run(p)
|
|
492
|
+
self.assertEqual(code, 1)
|
|
493
|
+
self.assertIn("game controller", out)
|
|
494
|
+
finally:
|
|
495
|
+
os.remove(p)
|
|
496
|
+
|
|
497
|
+
def test_positive_thumbnail_grid_still_fails(self):
|
|
498
|
+
p = write_json([
|
|
499
|
+
{
|
|
500
|
+
"file": "ai_p8.png",
|
|
501
|
+
"mode": "text-to-image",
|
|
502
|
+
"aspect": "16:9",
|
|
503
|
+
"prompt": "energy grid operations page with a thumbnail grid layout in the center",
|
|
504
|
+
}
|
|
505
|
+
])
|
|
506
|
+
try:
|
|
507
|
+
code, out = run(p)
|
|
508
|
+
self.assertEqual(code, 1)
|
|
509
|
+
self.assertIn("thumbnail grid", out)
|
|
510
|
+
finally:
|
|
511
|
+
os.remove(p)
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
if __name__ == "__main__":
|
|
515
|
+
unittest.main(verbosity=2)
|