@scemoon/cdh 1.0.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/ai-dlc-skill/SKILL.md +75 -0
- package/ai-dlc-skill/agents/deliver-agent.md +24 -0
- package/ai-dlc-skill/agents/master.md +44 -0
- package/ai-dlc-skill/agents/plan-agent.md +23 -0
- package/ai-dlc-skill/agents/understand-agent.md +23 -0
- package/ai-dlc-skill/agents/verify-agent.md +27 -0
- package/ai-dlc-skill/architecture/project-structure.md +78 -0
- package/ai-dlc-skill/brownfield/README.md +30 -0
- package/ai-dlc-skill/brownfield/generate-context.sh +64 -0
- package/ai-dlc-skill/brownfield/scripts/deps.sh +27 -0
- package/ai-dlc-skill/brownfield/scripts/discover.sh +34 -0
- package/ai-dlc-skill/brownfield/scripts/extract-api.sh +45 -0
- package/ai-dlc-skill/components/backend.md +34 -0
- package/ai-dlc-skill/components/desktop.md +30 -0
- package/ai-dlc-skill/components/mya.md +29 -0
- package/ai-dlc-skill/components/native.md +30 -0
- package/ai-dlc-skill/components/tta.md +29 -0
- package/ai-dlc-skill/components/web.md +31 -0
- package/ai-dlc-skill/components/wxa.md +29 -0
- package/ai-dlc-skill/contracts/README.md +25 -0
- package/ai-dlc-skill/core/adaptive-flow.md +36 -0
- package/ai-dlc-skill/core/security.md +29 -0
- package/ai-dlc-skill/cross-tool/cline/export.sh +31 -0
- package/ai-dlc-skill/cross-tool/copilot/export.sh +47 -0
- package/ai-dlc-skill/cross-tool/cursor/export.sh +32 -0
- package/ai-dlc-skill/cross-tool/export.sh +22 -0
- package/ai-dlc-skill/cross-tool/onecode/config.yaml.tpl +17 -0
- package/ai-dlc-skill/cross-tool/onecode/export-skills.sh +31 -0
- package/ai-dlc-skill/cross-tool/onecode/export.sh +48 -0
- package/ai-dlc-skill/phases/deliver/entry.md +26 -0
- package/ai-dlc-skill/phases/deliver/lifecycle.md +185 -0
- package/ai-dlc-skill/phases/deliver/prompt.md +40 -0
- package/ai-dlc-skill/phases/deliver/rules.md +61 -0
- package/ai-dlc-skill/phases/plan/entry.md +25 -0
- package/ai-dlc-skill/phases/plan/lifecycle.md +204 -0
- package/ai-dlc-skill/phases/plan/prompt.md +38 -0
- package/ai-dlc-skill/phases/plan/rules.md +25 -0
- package/ai-dlc-skill/phases/understand/entry.md +26 -0
- package/ai-dlc-skill/phases/understand/lifecycle.md +184 -0
- package/ai-dlc-skill/phases/understand/prompt.md +41 -0
- package/ai-dlc-skill/phases/understand/rules.md +37 -0
- package/ai-dlc-skill/phases/verify/entry.md +26 -0
- package/ai-dlc-skill/phases/verify/lifecycle.md +192 -0
- package/ai-dlc-skill/phases/verify/prompt.md +43 -0
- package/ai-dlc-skill/phases/verify/rules.md +73 -0
- package/ai-dlc-skill/practices/bdd.md +91 -0
- package/ai-dlc-skill/practices/sdd.md +84 -0
- package/ai-dlc-skill/practices/tdd.md +95 -0
- package/ai-dlc-skill/providers/README.md +114 -0
- package/ai-dlc-skill/providers/aliyun/deployment.yaml +66 -0
- package/ai-dlc-skill/providers/aliyun/preview.yaml +84 -0
- package/ai-dlc-skill/providers/aliyun/provider.yaml +160 -0
- package/ai-dlc-skill/providers/tcb/deployment.yaml +69 -0
- package/ai-dlc-skill/providers/tcb/preview.yaml +83 -0
- package/ai-dlc-skill/providers/tcb/provider.yaml +172 -0
- package/ai-dlc-skill/requirements.md +140 -0
- package/ai-dlc-skill/skill.yaml +147 -0
- package/ai-dlc-skill/templates/integration/CHANGELOG.md +41 -0
- package/ai-dlc-skill/templates/integration/asyncapi.yaml +43 -0
- package/ai-dlc-skill/templates/integration/contract-diff.md +63 -0
- package/ai-dlc-skill/templates/integration/contract-spec.md +49 -0
- package/ai-dlc-skill/templates/integration/openapi.yaml +18 -0
- package/ai-dlc-skill/templates/integration/runtime-contract.yaml +36 -0
- package/ai-dlc-skill/templates/plan/design.md +49 -0
- package/ai-dlc-skill/templates/plan/task-list.md +32 -0
- package/ai-dlc-skill/templates/project/README.md +127 -0
- package/ai-dlc-skill/templates/project/template.md +119 -0
- package/ai-dlc-skill/templates/understand/feature.feature +23 -0
- package/ai-dlc-skill/templates/understand/intent.md +29 -0
- package/ai-dlc-skill/templates/understand/spec-delta.md +47 -0
- package/ai-dlc-skill/templates/verify/test-unit.py +27 -0
- package/ai-dlc-skill/walkthrough/collect.sh +50 -0
- package/ai-dlc-skill/walkthrough/template.md +54 -0
- package/ai-dlc-skill/workflows/ai-dlc.yaml +110 -0
- package/ai-dlc-skill/workflows/deployment.yaml +199 -0
- package/cdh/__init__.py +0 -0
- package/cdh/__main__.py +4 -0
- package/cdh/__pycache__/__init__.cpython-313.pyc +0 -0
- package/cdh/__pycache__/__init__.cpython-314.pyc +0 -0
- package/cdh/__pycache__/cli.cpython-314.pyc +0 -0
- package/cdh/__pycache__/scaffold.cpython-313.pyc +0 -0
- package/cdh/__pycache__/scaffold.cpython-314.pyc +0 -0
- package/cdh/cli.py +361 -0
- package/cdh/scaffold.py +312 -0
- package/cli.js +2 -0
- package/onecode/__init__.py +1 -0
- package/onecode/__main__.py +4 -0
- package/onecode/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/__pycache__/cli.cpython-314.pyc +0 -0
- package/onecode/__pycache__/commands.cpython-314.pyc +0 -0
- package/onecode/__pycache__/config.cpython-314.pyc +0 -0
- package/onecode/__pycache__/config_screen.cpython-314.pyc +0 -0
- package/onecode/__pycache__/mock_data.cpython-314.pyc +0 -0
- package/onecode/agent/__init__.py +0 -0
- package/onecode/agent/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/cdh_agent_acp.cpython-313.pyc +0 -0
- package/onecode/agent/__pycache__/cdh_agent_acp.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/cdh_loader.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/context.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/engine.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/harness_skill.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/hooks.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/onecode_agent_acp.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/permissions.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/permissions_store.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/session.cpython-314.pyc +0 -0
- package/onecode/agent/agents/__init__.py +29 -0
- package/onecode/agent/agents/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/agent/agents/__pycache__/types.cpython-314.pyc +0 -0
- package/onecode/agent/agents/types.py +662 -0
- package/onecode/agent/attachments.py +113 -0
- package/onecode/agent/cdh_loader.py +262 -0
- package/onecode/agent/context.py +338 -0
- package/onecode/agent/engine.py +1894 -0
- package/onecode/agent/hooks.py +86 -0
- package/onecode/agent/onecode_agent_acp.py +2203 -0
- package/onecode/agent/permissions.py +151 -0
- package/onecode/agent/permissions_store.py +62 -0
- package/onecode/agent/session.py +186 -0
- package/onecode/agent/snapshot.py +145 -0
- package/onecode/agent/tools/__init__.py +17 -0
- package/onecode/agent/tools/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/agent_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/apply_patch_tool.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/bash_tool.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/communication_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/config_tool.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/cron_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/errors.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/file_ops.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/file_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/git_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/lsp_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/mcp_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/permission_handler.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/permissions.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/protocol.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/registry.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/sandbox.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/schema_validation.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/skill_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/task_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/web_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/agent_tools.py +134 -0
- package/onecode/agent/tools/apply_patch_tool.py +144 -0
- package/onecode/agent/tools/bash_tool.py +91 -0
- package/onecode/agent/tools/communication_tools.py +149 -0
- package/onecode/agent/tools/config_tool.py +130 -0
- package/onecode/agent/tools/cron_tools.py +179 -0
- package/onecode/agent/tools/errors.py +17 -0
- package/onecode/agent/tools/file_ops.py +187 -0
- package/onecode/agent/tools/file_tools.py +226 -0
- package/onecode/agent/tools/git_tools.py +88 -0
- package/onecode/agent/tools/lsp_tools.py +404 -0
- package/onecode/agent/tools/mcp_tools.py +129 -0
- package/onecode/agent/tools/permission_handler.py +46 -0
- package/onecode/agent/tools/permissions.py +77 -0
- package/onecode/agent/tools/protocol.py +20 -0
- package/onecode/agent/tools/registry.py +134 -0
- package/onecode/agent/tools/sandbox.py +264 -0
- package/onecode/agent/tools/schema_validation.py +100 -0
- package/onecode/agent/tools/skill_tools.py +52 -0
- package/onecode/agent/tools/task_tools.py +249 -0
- package/onecode/agent/tools/web_tools.py +170 -0
- package/onecode/builtin_skills/git/SKILL.md +64 -0
- package/onecode/builtin_skills/git/skill.yaml +7 -0
- package/onecode/builtin_skills/shell/SKILL.md +58 -0
- package/onecode/builtin_skills/shell/skill.yaml +8 -0
- package/onecode/cli.py +755 -0
- package/onecode/cloud/__init__.py +0 -0
- package/onecode/cloud/base.py +20 -0
- package/onecode/codebase/__init__.py +69 -0
- package/onecode/codebase/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/codebase/__pycache__/chunker.cpython-314.pyc +0 -0
- package/onecode/codebase/__pycache__/config.cpython-314.pyc +0 -0
- package/onecode/codebase/__pycache__/indexer.cpython-314.pyc +0 -0
- package/onecode/codebase/__pycache__/retriever.cpython-314.pyc +0 -0
- package/onecode/codebase/__pycache__/storage.cpython-314.pyc +0 -0
- package/onecode/codebase/__pycache__/tools.cpython-314.pyc +0 -0
- package/onecode/codebase/chunker.py +130 -0
- package/onecode/codebase/indexer.py +136 -0
- package/onecode/codebase/retriever.py +192 -0
- package/onecode/codebase/storage.py +130 -0
- package/onecode/codebase/tools.py +59 -0
- package/onecode/commands.py +276 -0
- package/onecode/config.py +285 -0
- package/onecode/config_screen.py +594 -0
- package/onecode/cron/__init__.py +3 -0
- package/onecode/lsp/__init__.py +3 -0
- package/onecode/mcp/__init__.py +4 -0
- package/onecode/mcp/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/mcp/__pycache__/client.cpython-314.pyc +0 -0
- package/onecode/mcp/__pycache__/manager.cpython-314.pyc +0 -0
- package/onecode/mcp/client.py +193 -0
- package/onecode/mcp/manager.py +191 -0
- package/onecode/memory/__init__.py +95 -0
- package/onecode/memory/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/memory/__pycache__/backend.cpython-314.pyc +0 -0
- package/onecode/memory/__pycache__/offload.cpython-314.pyc +0 -0
- package/onecode/memory/__pycache__/pyramid.cpython-314.pyc +0 -0
- package/onecode/memory/__pycache__/recall.cpython-314.pyc +0 -0
- package/onecode/memory/__pycache__/symbolic.cpython-314.pyc +0 -0
- package/onecode/memory/backend.py +185 -0
- package/onecode/memory/offload.py +114 -0
- package/onecode/memory/pyramid.py +202 -0
- package/onecode/memory/recall.py +168 -0
- package/onecode/memory/symbolic.py +164 -0
- package/onecode/models/__init__.py +4 -0
- package/onecode/models/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/models/__pycache__/errors.cpython-314.pyc +0 -0
- package/onecode/models/__pycache__/messages.cpython-314.pyc +0 -0
- package/onecode/models/__pycache__/provider.cpython-314.pyc +0 -0
- package/onecode/models/__pycache__/registry.cpython-314.pyc +0 -0
- package/onecode/models/errors.py +94 -0
- package/onecode/models/messages.py +662 -0
- package/onecode/models/provider.py +450 -0
- package/onecode/models/providers/__init__.py +17 -0
- package/onecode/models/providers/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/anthropic_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/deepseek_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/glm_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/minimax_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/minimaxi_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/mock_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/ollama_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/openai_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/anthropic_provider.py +224 -0
- package/onecode/models/providers/deepseek_provider.py +210 -0
- package/onecode/models/providers/glm_provider.py +154 -0
- package/onecode/models/providers/minimax_provider.py +154 -0
- package/onecode/models/providers/minimaxi_provider.py +363 -0
- package/onecode/models/providers/ollama_provider.py +96 -0
- package/onecode/models/providers/openai_provider.py +233 -0
- package/onecode/models/registry.py +212 -0
- package/onecode/server/__init__.py +3 -0
- package/onecode/server/app.py +224 -0
- package/onecode/skills/__init__.py +11 -0
- package/onecode/skills/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/skills/__pycache__/argument_substitution.cpython-314.pyc +0 -0
- package/onecode/skills/__pycache__/create.cpython-314.pyc +0 -0
- package/onecode/skills/__pycache__/frontmatter.cpython-314.pyc +0 -0
- package/onecode/skills/__pycache__/loader.cpython-314.pyc +0 -0
- package/onecode/skills/__pycache__/manager.cpython-314.pyc +0 -0
- package/onecode/skills/__pycache__/model.cpython-314.pyc +0 -0
- package/onecode/skills/argument_substitution.py +39 -0
- package/onecode/skills/create.py +56 -0
- package/onecode/skills/frontmatter.py +33 -0
- package/onecode/skills/loader.py +157 -0
- package/onecode/skills/manager.py +75 -0
- package/onecode/skills/model.py +43 -0
- package/onecode/storage/__init__.py +0 -0
- package/onecode/storage/activity.py +64 -0
- package/onecode/storage/project.py +54 -0
- package/onecode/storage/session.py +113 -0
- package/onecode/tasks/__init__.py +26 -0
- package/onecode/tasks/manager.py +219 -0
- package/onecode/tasks/models.py +240 -0
- package/onecode/trace/__init__.py +0 -0
- package/onecode/trace/tracer.py +174 -0
- package/onecode/utils/__init__.py +0 -0
- package/onecode/utils/helpers.py +20 -0
- package/onecode-cli.js +2 -0
- package/package.json +32 -0
- package/pyproject.toml +60 -0
- package/run.js +86 -0
- package/tui/__init__.py +46 -0
- package/tui/__main__.py +4 -0
- package/tui/__pycache__/__init__.cpython-314.pyc +0 -0
- package/tui/__pycache__/_loop.cpython-314.pyc +0 -0
- package/tui/__pycache__/_path_fuzzy_search.cpython-314.pyc +0 -0
- package/tui/__pycache__/_path_match.cpython-314.pyc +0 -0
- package/tui/__pycache__/agent.cpython-314.pyc +0 -0
- package/tui/__pycache__/agent_schema.cpython-314.pyc +0 -0
- package/tui/__pycache__/agents.cpython-314.pyc +0 -0
- package/tui/__pycache__/answer.cpython-314.pyc +0 -0
- package/tui/__pycache__/app.cpython-314.pyc +0 -0
- package/tui/__pycache__/atomic.cpython-314.pyc +0 -0
- package/tui/__pycache__/complete.cpython-314.pyc +0 -0
- package/tui/__pycache__/constants.cpython-314.pyc +0 -0
- package/tui/__pycache__/conversation_markdown.cpython-314.pyc +0 -0
- package/tui/__pycache__/danger.cpython-314.pyc +0 -0
- package/tui/__pycache__/db.cpython-314.pyc +0 -0
- package/tui/__pycache__/dec.cpython-314.pyc +0 -0
- package/tui/__pycache__/directory.cpython-314.pyc +0 -0
- package/tui/__pycache__/directory_suggester.cpython-314.pyc +0 -0
- package/tui/__pycache__/directory_watcher.cpython-314.pyc +0 -0
- package/tui/__pycache__/format_path.cpython-314.pyc +0 -0
- package/tui/__pycache__/fuzzy.cpython-314.pyc +0 -0
- package/tui/__pycache__/fuzzy_index.cpython-314.pyc +0 -0
- package/tui/__pycache__/history.cpython-314.pyc +0 -0
- package/tui/__pycache__/jsonrpc.cpython-314.pyc +0 -0
- package/tui/__pycache__/menus.cpython-314.pyc +0 -0
- package/tui/__pycache__/message_log.cpython-314.pyc +0 -0
- package/tui/__pycache__/messages.cpython-314.pyc +0 -0
- package/tui/__pycache__/path_complete.cpython-314.pyc +0 -0
- package/tui/__pycache__/path_filter.cpython-314.pyc +0 -0
- package/tui/__pycache__/paths.cpython-314.pyc +0 -0
- package/tui/__pycache__/pill.cpython-314.pyc +0 -0
- package/tui/__pycache__/platform_commands.cpython-314.pyc +0 -0
- package/tui/__pycache__/protocol.cpython-314.pyc +0 -0
- package/tui/__pycache__/session_tracker.cpython-314.pyc +0 -0
- package/tui/__pycache__/settings.cpython-314.pyc +0 -0
- package/tui/__pycache__/settings_schema.cpython-314.pyc +0 -0
- package/tui/__pycache__/shell.cpython-314.pyc +0 -0
- package/tui/__pycache__/shell_read.cpython-314.pyc +0 -0
- package/tui/__pycache__/slash_command.cpython-314.pyc +0 -0
- package/tui/__pycache__/version.cpython-314.pyc +0 -0
- package/tui/_loop.py +86 -0
- package/tui/_path_fuzzy_search.py +48 -0
- package/tui/_path_match.py +141 -0
- package/tui/about.py +95 -0
- package/tui/acp/__pycache__/agent.cpython-314.pyc +0 -0
- package/tui/acp/__pycache__/api.cpython-314.pyc +0 -0
- package/tui/acp/__pycache__/encode_tool_call_id.cpython-314.pyc +0 -0
- package/tui/acp/__pycache__/messages.cpython-314.pyc +0 -0
- package/tui/acp/__pycache__/prompt.cpython-314.pyc +0 -0
- package/tui/acp/__pycache__/protocol.cpython-314.pyc +0 -0
- package/tui/acp/agent.py +886 -0
- package/tui/acp/api.py +55 -0
- package/tui/acp/encode_tool_call_id.py +12 -0
- package/tui/acp/messages.py +190 -0
- package/tui/acp/prompt.py +110 -0
- package/tui/acp/protocol.py +462 -0
- package/tui/agent.py +70 -0
- package/tui/agent_schema.py +76 -0
- package/tui/agents.py +45 -0
- package/tui/ansi/__init__.py +1 -0
- package/tui/ansi/__pycache__/__init__.cpython-314.pyc +0 -0
- package/tui/ansi/__pycache__/_ansi.cpython-314.pyc +0 -0
- package/tui/ansi/__pycache__/_ansi_colors.cpython-314.pyc +0 -0
- package/tui/ansi/__pycache__/_control_codes.cpython-314.pyc +0 -0
- package/tui/ansi/__pycache__/_keys.cpython-314.pyc +0 -0
- package/tui/ansi/__pycache__/_sgr_styles.cpython-314.pyc +0 -0
- package/tui/ansi/__pycache__/_stream_parser.cpython-314.pyc +0 -0
- package/tui/ansi/_ansi.py +1689 -0
- package/tui/ansi/_ansi_colors.py +264 -0
- package/tui/ansi/_control_codes.py +37 -0
- package/tui/ansi/_keys.py +251 -0
- package/tui/ansi/_sgr_styles.py +64 -0
- package/tui/ansi/_stream_parser.py +418 -0
- package/tui/answer.py +12 -0
- package/tui/app.py +1236 -0
- package/tui/atomic.py +37 -0
- package/tui/cli.py +313 -0
- package/tui/code_analyze.py +27 -0
- package/tui/complete.py +38 -0
- package/tui/constants.py +61 -0
- package/tui/conversation_markdown.py +30 -0
- package/tui/danger.py +372 -0
- package/tui/data/agents/ampcode.com.toml +51 -0
- package/tui/data/agents/augmentcode.com.toml +40 -0
- package/tui/data/agents/cdh.cloud-dev-harness.toml +22 -0
- package/tui/data/agents/claude.com.toml +41 -0
- package/tui/data/agents/copilot.github.com.toml +29 -0
- package/tui/data/agents/crowai.dev.toml +35 -0
- package/tui/data/agents/cursor.com.toml +38 -0
- package/tui/data/agents/deepagents.langchain.com +33 -0
- package/tui/data/agents/docker.com.toml +59 -0
- package/tui/data/agents/geminicli.com.toml +28 -0
- package/tui/data/agents/goose.ai.toml +51 -0
- package/tui/data/agents/inference.huggingface.co.toml +41 -0
- package/tui/data/agents/kimi.com.toml +35 -0
- package/tui/data/agents/kiro.dev.toml +42 -0
- package/tui/data/agents/openai.com.toml +53 -0
- package/tui/data/agents/openclaw.ai.toml +37 -0
- package/tui/data/agents/opencode.ai.toml +39 -0
- package/tui/data/agents/openhands.dev.toml +45 -0
- package/tui/data/agents/stakpak.dev.toml +61 -0
- package/tui/data/agents/vibe.mistral.ai.toml +30 -0
- package/tui/data/agents/vtcode.dev.toml +62 -0
- package/tui/data/images/frog.png +0 -0
- package/tui/data/sounds/question.wav +0 -0
- package/tui/data/sounds/turn-over.wav +0 -0
- package/tui/db.py +190 -0
- package/tui/dec.py +332 -0
- package/tui/directory.py +234 -0
- package/tui/directory_suggester.py +93 -0
- package/tui/directory_watcher.py +197 -0
- package/tui/format_path.py +25 -0
- package/tui/fuzzy.py +140 -0
- package/tui/fuzzy_index.py +275 -0
- package/tui/gist.py +33 -0
- package/tui/history.py +138 -0
- package/tui/jsonrpc.py +578 -0
- package/tui/menus.py +14 -0
- package/tui/message_log.py +69 -0
- package/tui/messages.py +139 -0
- package/tui/option_content.py +51 -0
- package/tui/os.py +0 -0
- package/tui/path_complete.py +217 -0
- package/tui/path_filter.py +124 -0
- package/tui/paths.py +71 -0
- package/tui/pill.py +23 -0
- package/tui/platform_commands.py +52 -0
- package/tui/prompt/__pycache__/extract.cpython-314.pyc +0 -0
- package/tui/prompt/__pycache__/resource.cpython-314.pyc +0 -0
- package/tui/prompt/extract.py +19 -0
- package/tui/prompt/resource.py +68 -0
- package/tui/protocol.py +28 -0
- package/tui/screens/__init__.py +0 -0
- package/tui/screens/__pycache__/__init__.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/log.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/main.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/projects_screen.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/sessions.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/settings.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/store.cpython-314.pyc +0 -0
- package/tui/screens/action_modal.py +94 -0
- package/tui/screens/agent_modal.py +175 -0
- package/tui/screens/command_edit_modal.py +74 -0
- package/tui/screens/log.py +553 -0
- package/tui/screens/main.py +411 -0
- package/tui/screens/main.tcss +655 -0
- package/tui/screens/permissions.py +404 -0
- package/tui/screens/permissions.tcss +72 -0
- package/tui/screens/projects.tcss +66 -0
- package/tui/screens/projects_app.py +319 -0
- package/tui/screens/projects_screen.py +142 -0
- package/tui/screens/session_resume_modal.py +172 -0
- package/tui/screens/session_resume_modal.tcss +35 -0
- package/tui/screens/sessions.py +166 -0
- package/tui/screens/sessions.tcss +119 -0
- package/tui/screens/settings.py +254 -0
- package/tui/screens/settings.tcss +101 -0
- package/tui/screens/store.py +500 -0
- package/tui/screens/store.tcss +274 -0
- package/tui/screens/tool_content_screen.py +59 -0
- package/tui/session_tracker.py +120 -0
- package/tui/settings.py +353 -0
- package/tui/settings_schema.py +431 -0
- package/tui/shell.py +304 -0
- package/tui/shell_read.py +42 -0
- package/tui/slash_command.py +34 -0
- package/tui/tui.tcss +246 -0
- package/tui/twitter.py +38 -0
- package/tui/version.py +80 -0
- package/tui/visuals/__init__.py +0 -0
- package/tui/visuals/__pycache__/__init__.cpython-314.pyc +0 -0
- package/tui/visuals/__pycache__/columns.cpython-314.pyc +0 -0
- package/tui/visuals/columns.py +273 -0
- package/tui/widgets/__init__.py +0 -0
- package/tui/widgets/__pycache__/__init__.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/acp_content.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/agent_response.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/agent_thought.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/ask_user.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/condensed_path.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/context_stats.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/conversation.cpython-313.pyc +0 -0
- package/tui/widgets/__pycache__/conversation.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/diff_view.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/directory_input.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/flash.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/future_text.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/grid_select.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/highlighted_textarea.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/mandelbrot.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/markdown_note.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/menu.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/modified_files.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/non_selectable_label.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/note.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/path_search.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/plan.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/project_directory_tree.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/project_grid_select.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/project_summary.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/prompt.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/question.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/session_grid_select.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/session_summary.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/session_tabs.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/shell_result.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/shell_terminal.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/side_bar.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/slash_complete.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/strike_text.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/subagent.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/terminal.cpython-313.pyc +0 -0
- package/tui/widgets/__pycache__/terminal.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/throbber.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/tool_call.cpython-313.pyc +0 -0
- package/tui/widgets/__pycache__/tool_call.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/user_input.cpython-314.pyc +0 -0
- package/tui/widgets/acp_content.py +70 -0
- package/tui/widgets/agent_response.py +77 -0
- package/tui/widgets/agent_thought.py +168 -0
- package/tui/widgets/ask_user.py +264 -0
- package/tui/widgets/command_pane.py +223 -0
- package/tui/widgets/condensed_path.py +115 -0
- package/tui/widgets/context_stats.py +66 -0
- package/tui/widgets/conversation.py +2441 -0
- package/tui/widgets/danger_warning.py +65 -0
- package/tui/widgets/diff_view.py +59 -0
- package/tui/widgets/directory_input.py +8 -0
- package/tui/widgets/flash.py +81 -0
- package/tui/widgets/future_text.py +126 -0
- package/tui/widgets/grid_select.py +234 -0
- package/tui/widgets/highlighted_textarea.py +180 -0
- package/tui/widgets/mandelbrot.py +294 -0
- package/tui/widgets/markdown_note.py +13 -0
- package/tui/widgets/menu.py +147 -0
- package/tui/widgets/modified_files.py +106 -0
- package/tui/widgets/non_selectable_label.py +5 -0
- package/tui/widgets/note.py +18 -0
- package/tui/widgets/path_search.py +492 -0
- package/tui/widgets/plan.py +263 -0
- package/tui/widgets/project_directory_tree.py +90 -0
- package/tui/widgets/project_grid_select.py +35 -0
- package/tui/widgets/project_summary.py +33 -0
- package/tui/widgets/prompt.py +795 -0
- package/tui/widgets/question.py +360 -0
- package/tui/widgets/session_grid_select.py +224 -0
- package/tui/widgets/session_summary.py +115 -0
- package/tui/widgets/session_tabs.py +188 -0
- package/tui/widgets/shell_result.py +35 -0
- package/tui/widgets/shell_terminal.py +40 -0
- package/tui/widgets/side_bar.py +114 -0
- package/tui/widgets/slash_complete.py +235 -0
- package/tui/widgets/strike_text.py +70 -0
- package/tui/widgets/subagent.py +87 -0
- package/tui/widgets/terminal.py +577 -0
- package/tui/widgets/terminal_tool.py +351 -0
- package/tui/widgets/throbber.py +100 -0
- package/tui/widgets/tool_call.py +368 -0
- package/tui/widgets/user_input.py +23 -0
- package/tui/widgets/version.py +5 -0
- package/tui/widgets/welcome.py +31 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# AI-DLC Phase 3: Verify (验证)
|
|
2
|
+
|
|
3
|
+
Execute TDD red-green-refactor per BDD scenario at the right test layer, verify all scenarios, and run cross-component contract and cross-stack gates.
|
|
4
|
+
|
|
5
|
+
## Goal
|
|
6
|
+
|
|
7
|
+
Ensure every BDD scenario is correctly implemented at the right layer, every contract is backward-compatible, and the full stack e2e flow works — before delivery.
|
|
8
|
+
|
|
9
|
+
## Flow
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
Plan + Tasks approved
|
|
13
|
+
│
|
|
14
|
+
▼
|
|
15
|
+
For each unit in DAG order (within each affected component):
|
|
16
|
+
For each BDD scenario in unit:
|
|
17
|
+
│
|
|
18
|
+
RED: Write test at the right layer → confirm failure
|
|
19
|
+
GREEN: Write minimum implementation → confirm pass
|
|
20
|
+
REFACTOR: Clean up → confirm all tests still pass
|
|
21
|
+
│
|
|
22
|
+
─────────────────────────────────
|
|
23
|
+
Next unit...
|
|
24
|
+
│
|
|
25
|
+
▼
|
|
26
|
+
After per-component units: regenerate shared types + contract tests
|
|
27
|
+
tools/generate_shared.py
|
|
28
|
+
pytest tests/contract/
|
|
29
|
+
tools/contract_diff.py
|
|
30
|
+
│
|
|
31
|
+
▼
|
|
32
|
+
After contracts: cross-stack e2e against unified preview
|
|
33
|
+
pytest tests/cross-stack/
|
|
34
|
+
│
|
|
35
|
+
▼
|
|
36
|
+
Gate: All layers green + contracts compatible + cross-stack pass
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Test Layers
|
|
40
|
+
|
|
41
|
+
| Layer | When | Test Location | Run Against |
|
|
42
|
+
|-------|------|---------------|-------------|
|
|
43
|
+
| `unit` | Per function / module | `apps/{comp}/tests/unit/` | Local |
|
|
44
|
+
| `integration` | Component + its DB / internal API | `apps/{comp}/tests/integration/` | Local container |
|
|
45
|
+
| `e2e` | Whole component against preview | `apps/{comp}/tests/e2e/` | Component preview URL |
|
|
46
|
+
| `cross-stack` | Full multi-client ↔ backend flow | `tests/cross-stack/` | Unified stack preview URL |
|
|
47
|
+
| `contract` | Contract shape + backward compat | `tests/contract/` | Generated `packages/shared/` |
|
|
48
|
+
|
|
49
|
+
## TDD — Red
|
|
50
|
+
|
|
51
|
+
Write one pytest test per assertion in the BDD scenario, at the layer the test plan specified.
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
# apps/backend/tests/unit/test_auth.py
|
|
55
|
+
def test_login_valid_credentials():
|
|
56
|
+
result = authenticate("user@example.com", "correct123")
|
|
57
|
+
assert result.token is not None
|
|
58
|
+
assert result.expires_in == 3600
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pytest apps/backend/tests/unit/test_auth.py -v
|
|
63
|
+
# FAILED — authenticate() not defined (RED ✓)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Rule VRF-001:** Test must fail on first run.
|
|
67
|
+
|
|
68
|
+
## TDD — Green
|
|
69
|
+
|
|
70
|
+
Write the minimum code to make the test pass. No premature abstraction.
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
# apps/backend/src/auth/login.py
|
|
74
|
+
def authenticate(email, password):
|
|
75
|
+
if email == "user@example.com" and password == "correct123":
|
|
76
|
+
return AuthResult(token="jwt_token", expires_in=3600)
|
|
77
|
+
raise AuthError("Invalid credentials")
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Rule VRF-002:** Minimum code to pass.
|
|
81
|
+
|
|
82
|
+
## TDD — Refactor
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pytest --cov --cov-fail-under=80
|
|
86
|
+
# All tests passed, coverage ≥80% (REFACTOR ✓)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Rule VRF-003:** Behavior must not change. All existing tests must pass before and after.
|
|
90
|
+
|
|
91
|
+
## Contract Verification (INT-001, INT-002, INT-003)
|
|
92
|
+
|
|
93
|
+
After per-component units pass and before cross-stack e2e:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# 1. Regenerate shared types from contracts
|
|
97
|
+
tools/generate_shared.py
|
|
98
|
+
# → packages/shared/{api,events} updated
|
|
99
|
+
|
|
100
|
+
# 2. Run contract tests
|
|
101
|
+
pytest tests/contract/ --verbose
|
|
102
|
+
# → All contract scenarios pass (uses packages/shared)
|
|
103
|
+
|
|
104
|
+
# 3. Run contract compat check
|
|
105
|
+
tools/contract_diff.py --base main --head HEAD
|
|
106
|
+
# → exit 0 = backward-compatible
|
|
107
|
+
# → exit 1 = breaking change detected, BLOCKED unless human-approved
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Rule INT-001:** Contract tests must be 100% pass.
|
|
111
|
+
|
|
112
|
+
**Rule INT-002:** Any breaking contract change (field removed, type changed, status code changed, required field added) is BLOCKED until a human approves the major version bump and a migration note is added to `contracts/CHANGELOG.md`.
|
|
113
|
+
|
|
114
|
+
**Rule INT-003:** Shared types must be generated, not hand-written. CI runs `generate_shared` and fails the build if `packages/shared/` is out of date.
|
|
115
|
+
|
|
116
|
+
## Cross-Stack E2E (STK-001)
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
export STACK_URL=$(deploy_stack --preview --output url)
|
|
120
|
+
pytest tests/cross-stack/ --stack-url $STACK_URL --verbose
|
|
121
|
+
# All cross-stack scenarios pass
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Rule STK-001:** All `cross-stack` scenarios must pass. A single failure blocks delivery.
|
|
125
|
+
|
|
126
|
+
## BDD Scenario Verification (per layer)
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# Per component
|
|
130
|
+
pytest-bdd apps/backend/features/ --verbose
|
|
131
|
+
pytest-bdd apps/web/features/ --verbose # e.g. via cucumber-js
|
|
132
|
+
pytest-bdd apps/native/features/ --verbose # or via detox/cavy
|
|
133
|
+
pytest-bdd apps/desktop/features/ --verbose # or via spectron
|
|
134
|
+
pytest-bdd apps/wxa/features/ --verbose
|
|
135
|
+
pytest-bdd apps/mya/features/ --verbose
|
|
136
|
+
pytest-bdd apps/tta/features/ --verbose
|
|
137
|
+
|
|
138
|
+
# Cross-stack
|
|
139
|
+
pytest-bdd features/cross-stack/ --verbose
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Quality Gates (Backpressure)
|
|
143
|
+
|
|
144
|
+
All gates enforced on every attempt to mark a unit / change complete:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# Per component
|
|
148
|
+
pytest apps/{component}/ --cov --cov-fail-under=80 && \
|
|
149
|
+
pytest-bdd apps/{component}/features/ --verbose && \
|
|
150
|
+
bandit -r apps/{component}/src/ -q && \
|
|
151
|
+
! grep -rn "TODO\|FIXME\|HACK\|XXX" apps/{component}/src/
|
|
152
|
+
|
|
153
|
+
# Cross-component
|
|
154
|
+
pytest tests/contract/ && \
|
|
155
|
+
tools/contract_diff.py --base main --head HEAD
|
|
156
|
+
|
|
157
|
+
# Stack
|
|
158
|
+
pytest tests/cross-stack/ --stack-url $STACK_URL
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
| Gate | Threshold | Rule | Scope |
|
|
162
|
+
|------|-----------|------|-------|
|
|
163
|
+
| Unit/integration coverage | ≥80% | VRF-005 | Per component |
|
|
164
|
+
| BDD scenarios | 100% pass | VRF-004 | Per component |
|
|
165
|
+
| Security | 0 vulns | VRF-005 | Per component |
|
|
166
|
+
| No TODOs | 0 in src/ | VRF-005 | Per component |
|
|
167
|
+
| Contract tests | 100% pass | INT-001 | Cross-component |
|
|
168
|
+
| Contract compat | backward-compat | INT-002 | Cross-component |
|
|
169
|
+
| Shared types | generated, in sync | INT-003 | Cross-component |
|
|
170
|
+
| Cross-stack e2e | 100% pass | STK-001 | Stack |
|
|
171
|
+
|
|
172
|
+
## Artifacts
|
|
173
|
+
|
|
174
|
+
| Artifact | Location |
|
|
175
|
+
|----------|----------|
|
|
176
|
+
| TDD tests (unit/integration) | `apps/{comp}/tests/{unit,integration}/test_{feature}.py` |
|
|
177
|
+
| TDD tests (e2e) | `apps/{comp}/tests/e2e/test_{feature}.py` |
|
|
178
|
+
| BDD step defs (component) | `apps/{comp}/features/steps/test_{feature}_steps.py` |
|
|
179
|
+
| BDD step defs (cross-stack) | `features/cross-stack/steps/test_{feature}_steps.py` |
|
|
180
|
+
| Implementation | `apps/{comp}/src/{module}/{feature}.py` |
|
|
181
|
+
| Contract tests | `tests/contract/test_{contract}.py` |
|
|
182
|
+
| Cross-stack e2e | `tests/cross-stack/test_{flow}.py` |
|
|
183
|
+
| Contract diff | `openspec/changes/{id}/contract-diff.md` (filled) |
|
|
184
|
+
|
|
185
|
+
## Gate
|
|
186
|
+
|
|
187
|
+
**Before advancing to Deliver phase:**
|
|
188
|
+
- [ ] Per-component: All BDD scenarios pass (100%), coverage ≥80%, 0 vulns, no TODO
|
|
189
|
+
- [ ] Contracts: `tools/contract_diff.py` exits 0; `tests/contract/` 100% pass; `packages/shared/` regenerated and in sync
|
|
190
|
+
- [ ] Cross-stack: `tests/cross-stack/` 100% pass against stack preview
|
|
191
|
+
- [ ] `openspec/changes/{id}/contract-diff.md` is filled and reviewed
|
|
192
|
+
- [ ] All existing tests still pass
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Verify Phase Agent Prompt
|
|
2
|
+
|
|
3
|
+
你是一个 AI-DLC Verify Phase Agent。
|
|
4
|
+
由 Master Agent 委派处理测试验证。
|
|
5
|
+
|
|
6
|
+
## 输入
|
|
7
|
+
- `openspec/changes/{id}/design.md` 和 `task-list.md`
|
|
8
|
+
- BDD feature 文件
|
|
9
|
+
|
|
10
|
+
## 任务
|
|
11
|
+
|
|
12
|
+
1. **TDD Red-Green-Refactor**(按 DAG 顺序)
|
|
13
|
+
- 对每个 unit 的每个 BDD scenario:
|
|
14
|
+
- RED: 写 test → 确认失败
|
|
15
|
+
- GREEN: 写最小实现 → 确认通过
|
|
16
|
+
- REFACTOR: 重构清理 → 全部通过
|
|
17
|
+
- 测试按 layer 分类:unit / integration / e2e
|
|
18
|
+
|
|
19
|
+
2. **Contract Verification**
|
|
20
|
+
- 重新生成 `packages/shared/` 类型
|
|
21
|
+
- 运行 `pytest tests/contract/`
|
|
22
|
+
- 运行 `tools/contract_diff.py`
|
|
23
|
+
|
|
24
|
+
3. **Cross-Stack e2e**
|
|
25
|
+
- 对 unified preview 运行 `tests/cross-stack/`
|
|
26
|
+
|
|
27
|
+
4. **Quality Gates**
|
|
28
|
+
- coverage ≥ 80%
|
|
29
|
+
- BDD scenarios 100% pass
|
|
30
|
+
- 0 vulns, no TODO
|
|
31
|
+
|
|
32
|
+
## 输出产物
|
|
33
|
+
- `apps/{component}/tests/{unit,integration,e2e}/test_{feature}.py`
|
|
34
|
+
- `apps/{component}/features/steps/test_{feature}_steps.py`
|
|
35
|
+
- `apps/{component}/src/{module}/{feature}.py`
|
|
36
|
+
- `tests/contract/test_{contract}.py`
|
|
37
|
+
- `tests/cross-stack/test_{flow}.py`
|
|
38
|
+
- `openspec/changes/{id}/contract-diff.md`(填充)
|
|
39
|
+
|
|
40
|
+
## 约束
|
|
41
|
+
- 遵守 `rules.md` 中的 VRF-001 到 VRF-006
|
|
42
|
+
- 遵守 INT-001 到 INT-006
|
|
43
|
+
- 遵守 STK-001 到 STK-006
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Verify Rules (VRF-*) + Integration Rules (INT-*)
|
|
2
|
+
|
|
3
|
+
## VRF-001: TDD Red Phase
|
|
4
|
+
**Severity:** MUST
|
|
5
|
+
**Description:** Before writing implementation, write a test that asserts expected behavior. The test MUST fail on first run.
|
|
6
|
+
**Valid:** `pytest apps/backend/tests/unit/test_auth.py -k test_login` → FAILED.
|
|
7
|
+
**Invalid:** Test passes on first run.
|
|
8
|
+
|
|
9
|
+
## VRF-002: TDD Green Phase
|
|
10
|
+
**Severity:** MUST
|
|
11
|
+
**Description:** Write the minimum code needed to make the test pass. No premature abstraction.
|
|
12
|
+
**Valid:** Only the code path required by the test is implemented.
|
|
13
|
+
**Invalid:** Adding database, caching, or logging before the test requires it.
|
|
14
|
+
|
|
15
|
+
## VRF-003: TDD Refactor Phase
|
|
16
|
+
**Severity:** MUST
|
|
17
|
+
**Description:** After tests pass, refactor to improve code quality while keeping ALL tests green.
|
|
18
|
+
**Valid:** `pytest --cov --cov-fail-under=80` → all pass.
|
|
19
|
+
**Invalid:** Behavior change during refactoring.
|
|
20
|
+
|
|
21
|
+
## VRF-004: BDD Scenario Pass Gate
|
|
22
|
+
**Severity:** MUST
|
|
23
|
+
**Description:** ALL BDD scenarios MUST pass at every required layer before marking complete.
|
|
24
|
+
**Valid:** `pytest-bdd apps/{component}/features/ --verbose` → all pass.
|
|
25
|
+
**Invalid:** Any failing BDD scenario.
|
|
26
|
+
|
|
27
|
+
## VRF-005: Quality Gate Backpressure
|
|
28
|
+
**Severity:** MUST
|
|
29
|
+
**Description:** On every unit completion, ALL gates must pass: coverage ≥80%, BDD 100%, 0 vulns, no TODO.
|
|
30
|
+
**Valid:** `pytest --cov --cov-fail-under=80 && bandit -r src/ -q && ! grep -rn "TODO" src/`
|
|
31
|
+
**Invalid:** Any single gate fails.
|
|
32
|
+
|
|
33
|
+
## VRF-006: Test Layer Correctness
|
|
34
|
+
**Severity:** MUST
|
|
35
|
+
**Description:** Each BDD scenario MUST be tested at the layer the plan specified. Cross-stack ≠ unit.
|
|
36
|
+
**Valid:** Cross-stack scenarios in `tests/cross-stack/` against STACK_URL.
|
|
37
|
+
**Invalid:** Cross-stack scenario implemented as mocked unit test.
|
|
38
|
+
|
|
39
|
+
## INT-001: Contract as Source of Truth
|
|
40
|
+
**Severity:** MUST
|
|
41
|
+
**Description:** All cross-component APIs and events MUST be defined in `contracts/` (OpenAPI/AsyncAPI/GraphQL) and tagged with `INT-FR-*`.
|
|
42
|
+
**Valid:** `contracts/api/auth.yaml` defines POST /auth/login; components use generated types.
|
|
43
|
+
**Invalid:** Duplicate hand-written types across components with no contract file.
|
|
44
|
+
|
|
45
|
+
## INT-002: Backward-Compatibility by Default
|
|
46
|
+
**Severity:** MUST
|
|
47
|
+
**Description:** Contract changes MUST be backward-compatible. Breaking = field removed, type changed, status code changed, required field added. BLOCKED until human approves MAJOR bump + CHANGELOG entry.
|
|
48
|
+
**Valid:** Adding a new optional field (MINOR).
|
|
49
|
+
**Invalid:** Removing a field without human approval.
|
|
50
|
+
|
|
51
|
+
## INT-003: Generated Shared Types
|
|
52
|
+
**Severity:** MUST
|
|
53
|
+
**Description:** `packages/shared/` generated from `contracts/`. Component code MUST import from shared.
|
|
54
|
+
**Valid:** `git diff --exit-code packages/shared/` → clean after generation.
|
|
55
|
+
**Invalid:** Hand-edited files under `packages/shared/`.
|
|
56
|
+
|
|
57
|
+
## INT-004: Contract Tests at INT FR Level
|
|
58
|
+
**Severity:** MUST
|
|
59
|
+
**Description:** Every `INT-FR-*` MUST have contract tests in `tests/contract/` verifying schema.
|
|
60
|
+
**Valid:** Provider-agnostic contract tests using generated shared types.
|
|
61
|
+
**Invalid:** Contract tests calling real production backend.
|
|
62
|
+
|
|
63
|
+
## INT-005: Cross-Stack Feature Coverage
|
|
64
|
+
**Severity:** MUST
|
|
65
|
+
**Description:** Every `INT-FR-*` MUST have ≥3 scenarios in `features/cross-stack/` implemented in `tests/cross-stack/`.
|
|
66
|
+
**Valid:** Cross-stack scenarios running against unified STACK_URL.
|
|
67
|
+
**Invalid:** INT-FR without cross-stack feature file.
|
|
68
|
+
|
|
69
|
+
## INT-006: Contract Diff Artifact
|
|
70
|
+
**Severity:** MUST
|
|
71
|
+
**Description:** Every contract change MUST produce `openspec/changes/{id}/contract-diff.md`.
|
|
72
|
+
**Valid:** Generated by `tools/contract_diff.py` with added/removed/changed fields.
|
|
73
|
+
**Invalid:** Contract change merged without contract-diff.md.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Behavior-Driven Development (BDD)
|
|
2
|
+
|
|
3
|
+
BDD is the behavior specification and verification methodology used in Understand and Verify phases.
|
|
4
|
+
|
|
5
|
+
## Role in AI-DLC
|
|
6
|
+
|
|
7
|
+
| Phase | BDD Usage |
|
|
8
|
+
|-------|-----------|
|
|
9
|
+
| Understand | Feature files with Given/When/Then scenarios |
|
|
10
|
+
| Verify | pytest-bdd scenario verification against implementation |
|
|
11
|
+
| Deliver | BDD e2e tests against preview URL |
|
|
12
|
+
|
|
13
|
+
## Gherkin Syntax
|
|
14
|
+
|
|
15
|
+
| Keyword | Purpose |
|
|
16
|
+
|---------|---------|
|
|
17
|
+
| `Feature` | High-level feature description |
|
|
18
|
+
| `Scenario` | Single behavior example |
|
|
19
|
+
| `Given` | Precondition / starting state |
|
|
20
|
+
| `When` | Action performed |
|
|
21
|
+
| `Then` | Expected outcome |
|
|
22
|
+
| `And` / `But` | Additional clause |
|
|
23
|
+
| `Background` | Steps before every scenario |
|
|
24
|
+
| `Scenario Outline` | Template with Examples table |
|
|
25
|
+
| `@tag` | Metadata (FR ID, type) |
|
|
26
|
+
|
|
27
|
+
## Scenario Coverage Rules
|
|
28
|
+
|
|
29
|
+
Each FR must have at least 3 scenarios:
|
|
30
|
+
|
|
31
|
+
| Type | Purpose | Example Tag |
|
|
32
|
+
|------|---------|-------------|
|
|
33
|
+
| Positive | Happy path, should work | `@FR-001 @positive` |
|
|
34
|
+
| Negative | Error handling, should fail | `@FR-001 @negative` |
|
|
35
|
+
| Edge case | Boundary conditions | `@FR-001 @edge` |
|
|
36
|
+
|
|
37
|
+
## Example
|
|
38
|
+
|
|
39
|
+
```gherkin
|
|
40
|
+
@FR-001
|
|
41
|
+
Feature: User Login
|
|
42
|
+
|
|
43
|
+
@FR-001 @positive
|
|
44
|
+
Scenario: Successful login
|
|
45
|
+
Given the user is on the login page
|
|
46
|
+
When the user submits email "user@test.com" and password "correct123"
|
|
47
|
+
Then the user receives a JWT token
|
|
48
|
+
And the user is redirected to dashboard
|
|
49
|
+
|
|
50
|
+
@FR-001 @negative
|
|
51
|
+
Scenario: Login with wrong password
|
|
52
|
+
Given the user is on the login page
|
|
53
|
+
When the user submits email "user@test.com" and password "wrong"
|
|
54
|
+
Then the user sees error "Invalid credentials"
|
|
55
|
+
|
|
56
|
+
@FR-001 @edge
|
|
57
|
+
Scenario: Login with empty fields
|
|
58
|
+
Given the user is on the login page
|
|
59
|
+
When the user submits email "" and password ""
|
|
60
|
+
Then the user sees error "Email and password are required"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## pytest-bdd Integration
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
# features/steps/test_login_steps.py
|
|
67
|
+
from pytest_bdd import scenarios, given, when, then, parsers
|
|
68
|
+
|
|
69
|
+
scenarios("../auth/login.feature")
|
|
70
|
+
|
|
71
|
+
@given("the user is on the login page")
|
|
72
|
+
def login_page():
|
|
73
|
+
return LoginPage()
|
|
74
|
+
|
|
75
|
+
@when(parsers.parse("the user submits email {email} and password {password}"))
|
|
76
|
+
def submit(email, password):
|
|
77
|
+
...
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Verification
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Run all BDD scenarios
|
|
84
|
+
pytest-bdd features/ --verbose
|
|
85
|
+
|
|
86
|
+
# Run scenarios for a specific FR
|
|
87
|
+
pytest-bdd features/ -k "FR-001"
|
|
88
|
+
|
|
89
|
+
# BDD scenario coverage
|
|
90
|
+
pytest-bdd features/ --coverage
|
|
91
|
+
```
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Spec-Driven Development (SDD)
|
|
2
|
+
|
|
3
|
+
SDD is the specification methodology used in Understand and Plan phases.
|
|
4
|
+
|
|
5
|
+
## Role in AI-DLC
|
|
6
|
+
|
|
7
|
+
| Phase | SDD Usage |
|
|
8
|
+
|-------|-----------|
|
|
9
|
+
| Understand | Intent capture, spec delta with EARS |
|
|
10
|
+
| Plan | Design doc, task decomposition with DAG |
|
|
11
|
+
| Deliver | Artifact archiving |
|
|
12
|
+
|
|
13
|
+
## Core Artifacts
|
|
14
|
+
|
|
15
|
+
### Proposal (Why/What/Impact)
|
|
16
|
+
|
|
17
|
+
```markdown
|
|
18
|
+
## Change: CHG-001 — User Authentication
|
|
19
|
+
|
|
20
|
+
**Why:** Users need to securely access their accounts
|
|
21
|
+
**What:** Email + password login with JWT session
|
|
22
|
+
**Impact:** New auth module, changes to user model
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Spec Delta (EARS)
|
|
26
|
+
|
|
27
|
+
```markdown
|
|
28
|
+
## ADDED Requirements
|
|
29
|
+
|
|
30
|
+
### FR-001: User Authentication
|
|
31
|
+
|
|
32
|
+
**Priority:** P0
|
|
33
|
+
|
|
34
|
+
**Description (Event-Driven):**
|
|
35
|
+
When a user submits valid credentials, the system SHALL authenticate and return a JWT token.
|
|
36
|
+
|
|
37
|
+
**Acceptance Criteria:**
|
|
38
|
+
- AC1: Valid credentials return JWT with 1-hour expiry
|
|
39
|
+
- AC2: Invalid credentials return 401
|
|
40
|
+
- AC3: Empty fields return validation error
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Design Doc
|
|
44
|
+
|
|
45
|
+
```markdown
|
|
46
|
+
## Data Model: User
|
|
47
|
+
|
|
48
|
+
| Field | Type | Constraints |
|
|
49
|
+
|-------|------|-------------|
|
|
50
|
+
| id | UUID | PK |
|
|
51
|
+
| email | string | UNIQUE, NOT NULL |
|
|
52
|
+
|
|
53
|
+
## API: POST /auth/login
|
|
54
|
+
|
|
55
|
+
Request: `{email, password}` Response: `{token, expires_in}`
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Task List with DAG
|
|
59
|
+
|
|
60
|
+
```yaml
|
|
61
|
+
units:
|
|
62
|
+
- id: unit-1
|
|
63
|
+
name: Database schema
|
|
64
|
+
depends_on: []
|
|
65
|
+
- id: unit-2
|
|
66
|
+
name: Login endpoint
|
|
67
|
+
depends_on: [unit-1]
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## EARS Patterns
|
|
71
|
+
|
|
72
|
+
| Pattern | Syntax | Example |
|
|
73
|
+
|---------|--------|---------|
|
|
74
|
+
| Ubiquitous | `The system SHALL ...` | Always-hash passwords with bcrypt |
|
|
75
|
+
| Event-Driven | `When {event}, SHALL ...` | When user logs in, create session |
|
|
76
|
+
| State-Driven | `While {state}, SHALL ...` | While session active, auto-refresh |
|
|
77
|
+
| Unwanted | `If {condition}, SHALL ...` | If DB fails, return 503 |
|
|
78
|
+
| Optional | `Where {feature}, SHALL ...` | Where SSO enabled, skip password |
|
|
79
|
+
|
|
80
|
+
## Tools
|
|
81
|
+
|
|
82
|
+
- Spec format: Markdown with EARS
|
|
83
|
+
- Design: Markdown + Mermaid diagrams
|
|
84
|
+
- Tasks: YAML with DAG structure
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Test-Driven Development (TDD)
|
|
2
|
+
|
|
3
|
+
TDD is the implementation methodology used in the Verify phase.
|
|
4
|
+
|
|
5
|
+
## Role in AI-DLC
|
|
6
|
+
|
|
7
|
+
| Phase | TDD Usage |
|
|
8
|
+
|-------|-----------|
|
|
9
|
+
| Plan | Test plan written per scenario |
|
|
10
|
+
| Verify | Red → Green → Refactor per BDD scenario |
|
|
11
|
+
|
|
12
|
+
## Core Cycle
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
For each BDD scenario:
|
|
16
|
+
┌──────────────────┐
|
|
17
|
+
│ 1. RED │ Write pytest test → confirm FAILURE
|
|
18
|
+
│ 2. GREEN │ Write minimum implementation → confirm PASS
|
|
19
|
+
│ 3. REFACTOR │ Clean up → all tests still PASS
|
|
20
|
+
└──────────────────┘
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## RED Phase
|
|
24
|
+
|
|
25
|
+
Write a test that asserts the expected behavior. It must fail on first run.
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
# tests/unit/test_auth.py
|
|
29
|
+
def test_login_valid_credentials():
|
|
30
|
+
result = authenticate("user@test.com", "correct123")
|
|
31
|
+
assert result.token is not None
|
|
32
|
+
assert result.expires_in == 3600
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pytest tests/unit/test_auth.py -v
|
|
37
|
+
# FAILED — authenticate not defined ✓ (RED confirmed)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Rules:**
|
|
41
|
+
- Test written before implementation code
|
|
42
|
+
- Test must fail (confirms the assertion is valid)
|
|
43
|
+
- Test covers only this scenario's behavior
|
|
44
|
+
|
|
45
|
+
## GREEN Phase
|
|
46
|
+
|
|
47
|
+
Write the minimum code to make the test pass.
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
# src/auth/login.py
|
|
51
|
+
def authenticate(email, password):
|
|
52
|
+
if email == "user@test.com" and password == "correct123":
|
|
53
|
+
return AuthResult(token="jwt_placeholder", expires_in=3600)
|
|
54
|
+
raise AuthError("Invalid credentials")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pytest tests/unit/test_auth.py -v
|
|
59
|
+
# PASSED ✓ (GREEN)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Rules:**
|
|
63
|
+
- Minimum code to pass — no extras
|
|
64
|
+
- No premature optimization
|
|
65
|
+
- No new dependencies unless required
|
|
66
|
+
|
|
67
|
+
## REFACTOR Phase
|
|
68
|
+
|
|
69
|
+
Improve code quality without changing behavior.
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pytest --cov --cov-fail-under=80
|
|
73
|
+
# All tests passed, coverage ≥80% ✓ (REFACTOR)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Rules:**
|
|
77
|
+
- Keep all tests green
|
|
78
|
+
- No behavior changes
|
|
79
|
+
- Repeat for next scenario
|
|
80
|
+
|
|
81
|
+
## Naming Convention
|
|
82
|
+
|
|
83
|
+
| Artifact | Location | Example |
|
|
84
|
+
|----------|----------|---------|
|
|
85
|
+
| Tests | `tests/unit/test_{feature}.py` | `tests/unit/test_auth.py` |
|
|
86
|
+
| Step defs | `features/steps/test_{feature}_steps.py` | `features/steps/test_login_steps.py` |
|
|
87
|
+
| Source | `src/{module}/{feature}.py` | `src/auth/login.py` |
|
|
88
|
+
|
|
89
|
+
## Quality Gates
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
pytest --cov --cov-fail-under=80
|
|
93
|
+
pytest-bdd features/ --verbose
|
|
94
|
+
bandit -r src/ -q
|
|
95
|
+
```
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Cloud Providers
|
|
2
|
+
|
|
3
|
+
## Default: TCB (Tencent CloudBase)
|
|
4
|
+
|
|
5
|
+
TCB is the default cloud development platform. Aliyun is also supported.
|
|
6
|
+
|
|
7
|
+
The provider layer supports a **monorepo multi-component stack** (native + desktop + web + backend + wxa + mya + tta). Use the `deploy_stack` orchestrator instead of per-component CLI commands for shared environments.
|
|
8
|
+
|
|
9
|
+
## Provider Comparison
|
|
10
|
+
|
|
11
|
+
| Capability | TCB | Aliyun |
|
|
12
|
+
|-----------|-----|--------|
|
|
13
|
+
| **Functions** | CloudBase Functions | Function Compute (FC) |
|
|
14
|
+
| **Database** | DocDB + MySQL | TableStore + RDS |
|
|
15
|
+
| **Storage** | COS (Cloud Object Storage) | OSS (Object Storage Service) |
|
|
16
|
+
| **Hosting** | CloudBase Hosting + Preview | Static Website + CDN |
|
|
17
|
+
| **Stack preview URL** | `https://{env-id}.tcb-preview.com` (gateway) | `https://{gateway}.{region}.fc.devs.com` |
|
|
18
|
+
| **Default** | Yes | No |
|
|
19
|
+
|
|
20
|
+
## Stack Deploy
|
|
21
|
+
|
|
22
|
+
`deploy_stack` is the unified orchestrator. It deploys `backend` first, captures `BACKEND_URL`, then deploys all client components with `BACKEND_URL` injected. The output is `STACK_URL` (= `BACKEND_URL`) plus per-component URLs.
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
deploy_stack --preview --provider tcb
|
|
26
|
+
# → STACK_URL=https://{env-id}.tcb-preview.com
|
|
27
|
+
# → WEB_URL=https://{env-id}-{project}.tcb-preview.com
|
|
28
|
+
# → NATIVE_DIST_URL=internal distribution URL
|
|
29
|
+
# → DESKTOP_DIST_URL=internal distribution URL
|
|
30
|
+
# → WXA_URL/MYA_URL/TTA_URL=mini-program preview QR
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
deploy_stack --preview --provider aliyun
|
|
35
|
+
# → STACK_URL=https://{gateway}.{region}.fc.devs.com
|
|
36
|
+
# → WEB_URL=https://{bucket}.{region}.oss-website.aliyuncs.com
|
|
37
|
+
# → NATIVE_DIST_URL=internal distribution URL
|
|
38
|
+
# → DESKTOP_DIST_URL=internal distribution URL
|
|
39
|
+
# → WXA_URL/MYA_URL/TTA_URL=mini-program preview QR
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Build Config Injection
|
|
43
|
+
|
|
44
|
+
All client builds receive `BACKEND_URL` at build time. The orchestrator passes it; components must not hardcode URLs.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# web
|
|
48
|
+
pnpm --filter web build --env BACKEND_URL=$BACKEND_URL
|
|
49
|
+
|
|
50
|
+
# native
|
|
51
|
+
cd apps/native && BACKEND_URL=$BACKEND_URL pnpm build
|
|
52
|
+
|
|
53
|
+
# desktop
|
|
54
|
+
cd apps/desktop && BACKEND_URL=$BACKEND_URL pnpm build
|
|
55
|
+
|
|
56
|
+
# mini-programs (wxa, mya, tta)
|
|
57
|
+
cd apps/wxa && BACKEND_URL=$BACKEND_URL pnpm build
|
|
58
|
+
cd apps/mya && BACKEND_URL=$BACKEND_URL pnpm build
|
|
59
|
+
cd apps/tta && BACKEND_URL=$BACKEND_URL pnpm build
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Component URL Resolution
|
|
63
|
+
|
|
64
|
+
| Component | TCB | Aliyun |
|
|
65
|
+
|-----------|-----|--------|
|
|
66
|
+
| `backend` (gateway) | `https://{env-id}.tcb-preview.com` | `https://{gateway}.{region}.fc.devs.com` |
|
|
67
|
+
| `web` (hosting) | `https://{env-id}-{project}.tcb-preview.com` | `https://{bucket}.{region}.oss-website.aliyuncs.com` |
|
|
68
|
+
| `native` (distribution) | internal distribution URL | internal distribution URL |
|
|
69
|
+
| `desktop` (distribution) | internal distribution URL | internal distribution URL |
|
|
70
|
+
| `wxa` (mini-program) | mini-program preview QR | mini-program preview QR |
|
|
71
|
+
| `mya` (mini-program) | mini-program preview QR | mini-program preview QR |
|
|
72
|
+
| `tta` (mini-program) | mini-program preview QR | mini-program preview QR |
|
|
73
|
+
|
|
74
|
+
## BDD E2E Targets
|
|
75
|
+
|
|
76
|
+
| Test | Target |
|
|
77
|
+
|------|--------|
|
|
78
|
+
| `apps/backend/tests/e2e/` | `BACKEND_URL` |
|
|
79
|
+
| `apps/web/tests/e2e/` | `WEB_URL` + `BACKEND_URL` (as API root) |
|
|
80
|
+
| `apps/native/tests/e2e/` | `BACKEND_URL` (built into app) |
|
|
81
|
+
| `apps/desktop/tests/e2e/` | `BACKEND_URL` (built into app) |
|
|
82
|
+
| `apps/wxa/tests/e2e/` | `BACKEND_URL` (built into app) |
|
|
83
|
+
| `apps/mya/tests/e2e/` | `BACKEND_URL` (built into app) |
|
|
84
|
+
| `apps/tta/tests/e2e/` | `BACKEND_URL` (built into app) |
|
|
85
|
+
| `tests/cross-stack/` | `STACK_URL` (full flow) |
|
|
86
|
+
|
|
87
|
+
## Dynamic Preview URL
|
|
88
|
+
|
|
89
|
+
Preview URLs are resolved at deploy time based on the active provider:
|
|
90
|
+
|
|
91
|
+
- **TCB:** `deploy_stack --preview --provider tcb` → `STACK_URL=https://{env-id}.tcb-preview.com`
|
|
92
|
+
- **Aliyun:** `deploy_stack --preview --provider aliyun` → `STACK_URL=https://{gateway}.{region}.fc.devs.com`
|
|
93
|
+
|
|
94
|
+
Set as `STACK_URL` / `BACKEND_URL` / `WEB_URL` / per-component URLs as environment variables for BDD e2e tests:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
export STACK_URL=$(deploy_stack --preview --output url)
|
|
98
|
+
export BACKEND_URL=$STACK_URL
|
|
99
|
+
export WEB_URL=$(deploy_stack --preview --output web_url)
|
|
100
|
+
export NATIVE_URL=$(deploy_stack --preview --output native_url)
|
|
101
|
+
export DESKTOP_URL=$(deploy_stack --preview --output desktop_url)
|
|
102
|
+
pytest apps/web/tests/e2e/ --base-url $WEB_URL --api-url $BACKEND_URL
|
|
103
|
+
pytest apps/native/tests/e2e/ --backend-url $BACKEND_URL
|
|
104
|
+
pytest apps/desktop/tests/e2e/ --backend-url $BACKEND_URL
|
|
105
|
+
pytest tests/cross-stack/ --stack-url $STACK_URL
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Stack Rollback
|
|
109
|
+
|
|
110
|
+
Rollback is at the **stack** level: backend and all client components revert together to the last stable stack version.
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
deploy_stack --rollback ${LAST_STABLE_STACK_VERSION} --provider tcb
|
|
114
|
+
```
|