antigravity-ide 4.2.1 → 4.3.3
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/.agent/.shared/{design-philosophy → core/design-philosophy}/README.md +12 -1
- package/.agent/.shared/{ai-master → technical/ai-master}/README.md +12 -1
- package/.agent/.shared/{api-standards → technical/api-standards}/README.md +12 -1
- package/.agent/.shared/{database-master → technical/database-master}/README.md +12 -2
- package/.agent/.shared/{seo-master → technical/seo-master}/README.md +12 -1
- package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/README.md +12 -1
- package/.agent/ARCHITECTURE.md +16 -10
- package/.agent/ARCHITECTURE.vi.md +8 -8
- package/{GEMINI.md → .agent/GEMINI.md} +4 -5
- package/.agent/RESOURCES.md +6 -1
- package/.agent/agents/backend-specialist.md +154 -19
- package/.agent/agents/browser-subagent.md +45 -0
- package/.agent/agents/cloud-architect.md +108 -189
- package/.agent/agents/debugger.md +83 -182
- package/.agent/agents/documentation-writer.md +125 -72
- package/.agent/agents/frontend-specialist.md +40 -7
- package/.agent/agents/game-developer.md +111 -116
- package/.agent/agents/mobile-developer.md +108 -321
- package/.agent/agents/orchestrator.md +106 -366
- package/.agent/agents/performance-optimizer.md +105 -136
- package/.agent/agents/project-planner.md +132 -39
- package/.agent/agents/quality-inspector.md +136 -32
- package/.agent/agents/security-auditor.md +138 -15
- package/.agent/agents/seo-specialist.md +118 -72
- package/.agent/agents/test-engineer.md +142 -11
- package/.agent/brain/task.md +16 -0
- package/.agent/rules/GEMINI.md +63 -31
- package/.agent/rules/code-quality.md +34 -3
- package/.agent/rules/frontend.md +3 -3
- package/.agent/rules/strict-protocol.md +44 -3
- package/.agent/rules/system-update.md +56 -3
- package/.agent/skills/agent-backend-patterns/SKILL.md +16 -3
- package/.agent/skills/ai-engineer/SKILL.md +29 -16
- package/.agent/skills/api-documenter/SKILL.md +4 -4
- package/.agent/skills/app-builder/SKILL.md +1 -1
- package/.agent/skills/app-builder/tech-stack.md +2 -2
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +39 -79
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +53 -75
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +56 -119
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +61 -94
- package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +56 -82
- package/.agent/skills/brand-guidelines-anthropic/LICENSE.txt +202 -0
- package/.agent/skills/brand-guidelines-anthropic/SKILL.md +26 -0
- package/.agent/skills/brand-guidelines-anthropic/sub-skills/color-application.md +5 -0
- package/.agent/skills/brand-guidelines-anthropic/sub-skills/colors.md +14 -0
- package/.agent/skills/brand-guidelines-anthropic/sub-skills/font-management.md +6 -0
- package/.agent/skills/brand-guidelines-anthropic/sub-skills/shape-and-accent-colors.md +7 -0
- package/.agent/skills/brand-guidelines-anthropic/sub-skills/smart-font-application.md +6 -0
- package/.agent/skills/brand-guidelines-anthropic/sub-skills/text-styling.md +6 -0
- package/.agent/skills/brand-guidelines-anthropic/sub-skills/typography.md +7 -0
- package/.agent/skills/cloud-architect-master/SKILL.md +9 -4
- package/.agent/skills/cro-expert-kit/SKILL.md +9 -4
- package/.agent/skills/database-migration/SKILL.md +9 -3
- package/.agent/skills/deployment-engineer/SKILL.md +9 -3
- package/.agent/skills/frontend-design/ux-psychology.md +10 -585
- package/.agent/skills/full-stack-scaffold/SKILL.md +4 -4
- package/.agent/skills/game-development/2d-games/SKILL.md +4 -2
- package/.agent/skills/game-development/3d-games/SKILL.md +4 -2
- package/.agent/skills/game-development/SKILL.md +18 -149
- package/.agent/skills/game-development/game-art/SKILL.md +4 -2
- package/.agent/skills/game-development/game-audio/SKILL.md +4 -2
- package/.agent/skills/game-development/game-design/SKILL.md +4 -2
- package/.agent/skills/game-development/mobile-games/SKILL.md +4 -2
- package/.agent/skills/game-development/multiplayer/SKILL.md +4 -2
- package/.agent/skills/game-development/pc-games/SKILL.md +4 -2
- package/.agent/skills/game-development/vr-ar/SKILL.md +4 -2
- package/.agent/skills/game-development/web-games/SKILL.md +4 -2
- package/.agent/skills/geo-fundamentals/SKILL.md +9 -136
- package/.agent/skills/git-collaboration-master/SKILL.md +9 -4
- package/.agent/skills/i18n-localization/SKILL.md +10 -118
- package/.agent/skills/incident-responder/SKILL.md +9 -6
- package/.agent/skills/internal-comms-anthropic/LICENSE.txt +202 -0
- package/.agent/skills/internal-comms-anthropic/SKILL.md +33 -0
- package/.agent/skills/internal-comms-anthropic/examples/3p-updates.md +47 -0
- package/.agent/skills/internal-comms-anthropic/examples/company-newsletter.md +65 -0
- package/.agent/skills/internal-comms-anthropic/examples/faq-answers.md +30 -0
- package/.agent/skills/internal-comms-anthropic/examples/general-comms.md +16 -0
- package/.agent/skills/last30days/tests/__init__.py +1 -0
- package/.agent/skills/last30days/tests/test_cache.py +59 -0
- package/.agent/skills/last30days/tests/test_dates.py +114 -0
- package/.agent/skills/last30days/tests/test_dedupe.py +111 -0
- package/.agent/skills/last30days/tests/test_models.py +135 -0
- package/.agent/skills/last30days/tests/test_normalize.py +138 -0
- package/.agent/skills/last30days/tests/test_render.py +116 -0
- package/.agent/skills/last30days/tests/test_score.py +168 -0
- package/.agent/skills/legacy-modernizer/SKILL.md +9 -4
- package/.agent/skills/lint-and-validate/scripts/lint_runner.py +2 -14
- package/.agent/skills/loki-mode/.github/workflows/claude-code-review.yml +57 -0
- package/.agent/skills/loki-mode/.github/workflows/claude.yml +50 -0
- package/.agent/skills/loki-mode/.github/workflows/release.yml +128 -0
- package/.agent/skills/loki-mode/tests/run-all-tests.sh +78 -0
- package/.agent/skills/loki-mode/tests/test-agent-timeout.sh +348 -0
- package/.agent/skills/loki-mode/tests/test-bootstrap.sh +196 -0
- package/.agent/skills/loki-mode/tests/test-circuit-breaker.sh +389 -0
- package/.agent/skills/loki-mode/tests/test-state-recovery.sh +393 -0
- package/.agent/skills/loki-mode/tests/test-task-queue.sh +396 -0
- package/.agent/skills/loki-mode/tests/test-wrapper.sh +314 -0
- package/.agent/skills/mcp-builder/SKILL.md +21 -164
- package/.agent/skills/mobile-design/SKILL.md +21 -369
- package/.agent/skills/mobile-design/mobile-performance.md +1 -1
- package/.agent/skills/modern-web-architect/SKILL.md +12 -6
- package/.agent/skills/nextjs-react-expert/scripts/convert_rules.py +1 -1
- package/.agent/skills/penetration-tester-master/SKILL.md +9 -4
- package/.agent/skills/performance-engineer/SKILL.md +4 -5
- package/.agent/skills/production-code-audit/SKILL.md +6 -0
- package/.agent/skills/rust-pro/SKILL.md +0 -177
- package/.agent/skills/security-auditor/SKILL.md +35 -27
- package/.agent/skills/seo-expert-kit/SKILL.md +9 -4
- package/.agent/skills/shopify-development/scripts/tests/test_shopify_init.py +379 -0
- package/.agent/skills/tdd-master-workflow/SKILL.md +9 -3
- package/.agent/workflows/audit.md +30 -16
- package/.agent/workflows/brainstorm.md +33 -96
- package/.agent/workflows/create.md +37 -45
- package/.agent/workflows/debug.md +45 -84
- package/.agent/workflows/deploy.md +33 -158
- package/.agent/workflows/document.md +38 -15
- package/.agent/workflows/enhance.md +33 -48
- package/.agent/workflows/monitor.md +35 -14
- package/.agent/workflows/orchestrate.md +33 -218
- package/.agent/workflows/plan.md +39 -70
- package/.agent/workflows/security.md +35 -14
- package/.agent/workflows/seo.md +39 -16
- package/.agent/workflows/status.md +33 -72
- package/.agent/workflows/test.md +30 -127
- package/.agent/workflows/ui-ux-pro-max.md +24 -283
- package/LICENSE +22 -8
- package/README.md +105 -72
- package/README.vi.md +93 -110
- package/cli/create.js +275 -413
- package/cli/index.js +36 -24
- package/cli/lib/auto-update.js +14 -21
- package/cli/logic/product-skills.js +58 -0
- package/cli/logic/skill-definitions.js +0 -39
- package/cli/prompts.js +151 -145
- package/cli/skills/browser-subagent-core/SKILL.md +22 -0
- package/cli/tools/browser.js +75 -0
- package/cli/ui/dashboard.js +48 -0
- package/docs/AGENTS_GUIDE.vi.md +39 -45
- package/docs/CONTRIBUTING.vi.md +12 -3
- package/docs/{GEMINI_GUIDE.md → GEMINI_USAGE.md} +6 -6
- package/docs/GLOSSARY.vi.md +49 -30
- package/docs/HOW_ANTIGRAVITY_THINKS.vi.md +1 -1
- package/docs/OPERATIONAL_FLOW.vi.md +15 -0
- package/docs/{PUBLISHING.md → PUBLISHING_GUIDE.md} +31 -3
- package/docs/RULES_GUIDE.vi.md +67 -31
- package/docs/SHARED_LIBRARY_GUIDE.vi.md +18 -22
- package/docs/SKILLS_GUIDE.vi.md +119 -32
- package/docs/TROUBLESHOOTING.vi.md +10 -2
- package/docs/WORKFLOW_GUIDE.vi.md +57 -9
- package/package.json +32 -8
- package/setup.js +147 -114
- package/.agent/.shared/compliance/README.md +0 -19
- package/.agent/.shared/design-system/README.md +0 -18
- package/.agent/.shared/domain-blueprints/README.md +0 -18
- package/.agent/.shared/dx-toolkit/README.md +0 -19
- package/.agent/.shared/i18n-master/README.md +0 -18
- package/.agent/.shared/infra-blueprints/README.md +0 -18
- package/.agent/.shared/metrics/README.md +0 -17
- package/.agent/.shared/resilience-patterns/README.md +0 -19
- package/.agent/.shared/security-armor/README.md +0 -25
- package/.agent/.shared/testing-master/README.md +0 -20
- package/.agent/.shared/vitals-templates/README.md +0 -18
- package/.agent/agents/accessibility-expert.md +0 -22
- package/.agent/agents/api-architect.md +0 -22
- package/.agent/agents/backend-specialist.eco.md +0 -19
- package/.agent/agents/backend-specialist.instant.md +0 -19
- package/.agent/agents/codebase-expert.md +0 -23
- package/.agent/agents/compliance-expert.md +0 -22
- package/.agent/agents/data-scientist.md +0 -22
- package/.agent/agents/debugger.eco.md +0 -20
- package/.agent/agents/debugger.instant.md +0 -20
- package/.agent/agents/deep-thinker.ultra.md +0 -23
- package/.agent/agents/devex-optimizer.md +0 -22
- package/.agent/agents/devops-architect.md +0 -22
- package/.agent/agents/frontend-specialist.eco.md +0 -19
- package/.agent/agents/frontend-specialist.instant.md +0 -19
- package/.agent/agents/growth-engineer.md +0 -22
- package/.agent/agents/i18n-specialist.md +0 -21
- package/.agent/agents/legacy-modernizer.md +0 -22
- package/.agent/agents/microservices-specialist.md +0 -22
- package/.agent/agents/motion-designer.md +0 -22
- package/.agent/agents/orchestrator.creative.md +0 -28
- package/.agent/agents/orchestrator.eco.md +0 -29
- package/.agent/agents/orchestrator.instant.md +0 -29
- package/.agent/agents/orchestrator.ultra.md +0 -28
- package/.agent/agents/performance-benchmarker.md +0 -22
- package/.agent/agents/project-planner.eco.md +0 -19
- package/.agent/agents/project-planner.instant.md +0 -19
- package/.agent/agents/security-pentester.md +0 -22
- package/.agent/agents/serverless-expert.md +0 -22
- package/.agent/fastcode_index.json +0 -1038
- package/.agent/mcp_config.json +0 -24
- package/.agent/rules/GEMINI.eco.md +0 -37
- package/.agent/rules/GEMINI.instant.md +0 -37
- package/.agent/rules/api-spec.md +0 -28
- package/.agent/rules/database.md +0 -24
- package/.agent/rules/devops.md +0 -23
- package/.agent/rules/growth-strategy.md +0 -22
- package/.agent/rules/logging-monitoring.md +0 -22
- package/.agent/rules/quality-assurance.md +0 -22
- package/.agent/rules/system-reasoning.md +0 -20
- package/.agent/rules/ui-design.md +0 -23
- package/.agent/rules/ux-patterns.md +0 -23
- package/.agent/scripts/auto_preview.py +0 -148
- package/.agent/scripts/checklist.py +0 -252
- package/.agent/scripts/session_manager.py +0 -120
- package/.agent/scripts/simulation_install.js +0 -59
- package/.agent/scripts/sync_to_global.py +0 -78
- package/.agent/scripts/translate_workflows.py +0 -53
- package/.agent/scripts/verify_all.py +0 -327
- package/.agent/scripts/verify_shared_modules.js +0 -126
- package/.agent/skills/fastcode-search/SKILL.md +0 -46
- package/.agent/skills/fastcode-search/fastcode_config.example.json +0 -17
- package/.agent/skills/frontend-trends-2026/SKILL.md +0 -78
- package/.agent/skills/frontend-trends-2026/formulas/BentoGrid.tsx +0 -42
- package/.agent/skills/frontend-trends-2026/formulas/LiquidCard.tsx +0 -32
- package/.agent/skills/frontend-trends-2026/formulas/NeoButton.tsx +0 -27
- package/.agent/workflows/deep-security-audit.md +0 -9
- package/.agent/workflows/growth-max.md +0 -9
- package/.agent/workflows/performance-max.md +0 -9
- package/.editorconfig +0 -21
- package/.gitattributes +0 -7
- package/CHANGELOG.md +0 -32
- package/ERRORS.md +0 -67
- package/action.yml +0 -32
- package/antigravity-ide-logo.png +0 -0
- package/antigravity-ide-logo.svg +0 -24
- package/assets/skills-bundle.json +0 -1
- package/cli/manifest.js +0 -524
- package/cli/skills/fastcode.js +0 -181
- package/docs/AGENT_FLOW.md +0 -608
- package/docs/CONTRIBUTING.md +0 -46
- package/docs/COPYRIGHT.md +0 -57
- package/docs/DEPLOYMENT.md +0 -77
- package/docs/GLOSSARY.md +0 -109
- package/docs/MASTER_GUIDE.md +0 -103
- package/docs/OPERATIONAL_FLOW.md +0 -147
- package/docs/PLAN-upgrade-core-architecture.md +0 -71
- package/docs/SKILLS.md +0 -610
- package/docs/TROUBLESHOOTING.md +0 -43
- package/jest.config.js +0 -8
- package/scripts/bump.js +0 -93
- package/scripts/bundle-skills.js +0 -59
- package/scripts/internal/automation/auto-release.js +0 -177
- package/scripts/internal/fractalize-skills.js +0 -89
- package/scripts/internal/generate-skill-definitions.js +0 -134
- package/scripts/internal/internal/update-docs.js +0 -115
- package/scripts/internal/refactor-skill-content.js +0 -127
- package/scripts/internal/rename-skills.js +0 -96
- package/scripts/internal/sync-skills.js +0 -112
- package/scripts/internal/update-frontmatter-names.js +0 -99
- package/scripts/internal/verification/audit-dna.js +0 -56
- package/scripts/internal/verification/audit-skills.js +0 -65
- package/web/src/app/docs/guide/examples/brainstorm/page.mdx +0 -91
- package/web/src/app/docs/guide/examples/create/page.mdx +0 -84
- package/web/src/app/docs/guide/examples/debugging/page.mdx +0 -83
- package/web/src/app/docs/guide/examples/deployment/page.mdx +0 -93
- package/web/src/app/docs/guide/examples/new-feature/page.mdx +0 -102
- package/web/src/app/docs/guide/examples/orchestration/page.mdx +0 -99
- package/web/src/app/docs/guide/examples/plan/page.mdx +0 -76
- package/web/src/app/docs/guide/examples/preview/page.mdx +0 -77
- package/web/src/app/docs/guide/examples/status/page.mdx +0 -78
- package/web/src/app/docs/guide/examples/test/page.mdx +0 -80
- package/web/src/app/docs/guide/examples/ui-design/page.mdx +0 -90
- package/web/src/components/mdx/Callout.tsx +0 -60
- package/web/src/components/mdx/FeatureGrid.tsx +0 -38
- package/web/src/components/mdx/ProTips.tsx +0 -29
- package/web/src/components/mdx/StepList.tsx +0 -33
- package/web/src/components/mdx/Terminal.tsx +0 -58
- package/web/src/components/mdx/index.ts +0 -5
- package/web/src/mdx-components.tsx +0 -98
- /package/.agent/.shared/{design-philosophy → core/design-philosophy}/MANIFESTO.md +0 -0
- /package/.agent/.shared/{design-philosophy → core/design-philosophy}/checklists/tactile_audit.md +0 -0
- /package/.agent/.shared/{design-philosophy → core/design-philosophy}/checklists/visual_audit.md +0 -0
- /package/.agent/.shared/{design-philosophy → core/design-philosophy}/presets/linear_glow.json +0 -0
- /package/.agent/.shared/{dx-toolkit → core/dx-toolkit}/checklists/code_review.md +0 -0
- /package/.agent/.shared/{dx-toolkit → core/dx-toolkit}/presets/vscode_settings.json +0 -0
- /package/.agent/.shared/{metrics → core/metrics}/benchmarks.json +0 -0
- /package/.agent/.shared/{vitals-templates → core/vitals-templates}/audit_report.md +0 -0
- /package/.agent/.shared/{vitals-templates → core/vitals-templates}/plan_prd.md +0 -0
- /package/.agent/.shared/{ai-master → technical/ai-master}/best_patterns.md +0 -0
- /package/.agent/.shared/{ai-master → technical/ai-master}/checklists/prompt_audit.md +0 -0
- /package/.agent/.shared/{ai-master → technical/ai-master}/presets/model_configs.json +0 -0
- /package/.agent/.shared/{api-standards → technical/api-standards}/data +0 -0
- /package/.agent/.shared/{api-standards → technical/api-standards}/endpoints_naming.md +0 -0
- /package/.agent/.shared/{api-standards → technical/api-standards}/error_codes.csv +0 -0
- /package/.agent/.shared/{api-standards → technical/api-standards}/pagination_sorting.md +0 -0
- /package/.agent/.shared/{api-standards → technical/api-standards}/response_format.json +0 -0
- /package/.agent/.shared/{database-master → technical/database-master}/schemas/auth_rbac.sql +0 -0
- /package/.agent/.shared/{database-master → technical/database-master}/schemas/cms.sql +0 -0
- /package/.agent/.shared/{database-master → technical/database-master}/schemas/ecommerce.sql +0 -0
- /package/.agent/.shared/{design-system → technical/design-system}/brand_presets.json +0 -0
- /package/.agent/.shared/{design-system → technical/design-system}/micro_interactions.md +0 -0
- /package/.agent/.shared/{i18n-master → technical/i18n-master}/vi_tech_dictionary.csv +0 -0
- /package/.agent/.shared/{i18n-master → technical/i18n-master}/workflows.json +0 -0
- /package/.agent/.shared/{resilience-patterns → technical/resilience-patterns}/checklists/chaos_engineering.md +0 -0
- /package/.agent/.shared/{resilience-patterns → technical/resilience-patterns}/presets/circuit_breaker.json +0 -0
- /package/.agent/.shared/{security-armor → technical/security-armor}/checklists/vuln_scan.md +0 -0
- /package/.agent/.shared/{security-armor → technical/security-armor}/hardening.md +0 -0
- /package/.agent/.shared/{security-armor → technical/security-armor}/presets/helmet_config.json +0 -0
- /package/.agent/.shared/{seo-master → technical/seo-master}/checklists/technical_seo.md +0 -0
- /package/.agent/.shared/{seo-master → technical/seo-master}/presets/json_ld_schema.json +0 -0
- /package/.agent/.shared/{testing-master → technical/testing-master}/checklists/pre_release.md +0 -0
- /package/.agent/.shared/{testing-master → technical/testing-master}/scenarios.md +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/colors.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/icons.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/landing.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/products.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/react-performance.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/flutter.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/html-tailwind.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/jetpack-compose.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/nextjs.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/nuxt-ui.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/nuxtjs.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/react-native.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/react.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/shadcn.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/svelte.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/swiftui.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/stacks/vue.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/ux-guidelines.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/data/web-interface.csv +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/scripts/__pycache__/core.cpython-313.pyc +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/scripts/core.py +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/scripts/design_system.py +0 -0
- /package/.agent/.shared/{ui-ux-pro-max → technical/ui-ux-pro-max}/scripts/search.py +0 -0
- /package/.agent/.shared/{compliance → verticals/compliance}/legal_templates.md +0 -0
- /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/edtech.md +0 -0
- /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/fintech.md +0 -0
- /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/fnb_restaurant.md +0 -0
- /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/freelance_marketplace.md +0 -0
- /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/healthcare.md +0 -0
- /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/hospitality_tourism.md +0 -0
- /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/logistics.md +0 -0
- /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/marketing_automation.md +0 -0
- /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/personal_branding.md +0 -0
- /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/real_estate.md +0 -0
- /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/retail_ecommerce.md +0 -0
- /package/.agent/.shared/{domain-blueprints → verticals/domain-blueprints}/standard-pro-agents.md +0 -0
- /package/.agent/.shared/{infra-blueprints → verticals/infra-blueprints}/deployment_specs.md +0 -0
- /package/.agent/skills/ai-engineer/{resources → sub-skills}/ai_infra_stack.md +0 -0
- /package/.agent/skills/cloud-architect-master/{resources → sub-skills}/cost_optimization_checklist.md +0 -0
- /package/.agent/skills/cro-expert-kit/{resources → sub-skills}/psychological_triggers.md +0 -0
- /package/.agent/skills/database-migration/{resources → sub-skills}/zero_downtime_strategy.md +0 -0
- /package/.agent/skills/deployment-engineer/{resources → sub-skills}/k8s_best_practices.md +0 -0
- /package/.agent/skills/git-collaboration-master/{resources → sub-skills}/pr_template.md +0 -0
- /package/.agent/skills/incident-responder/{resources → sub-skills}/incident_severity_levels.md +0 -0
- /package/.agent/skills/legacy-modernizer/{resources → sub-skills}/strangler_fig_pattern.md +0 -0
- /package/.agent/skills/penetration-tester-master/{resources → sub-skills}/owasp_top_10_2025.md +0 -0
- /package/.agent/skills/production-code-audit/{resources → sub-skills}/solid_principles_cheat_sheet.md +0 -0
- /package/.agent/skills/seo-expert-kit/{resources → sub-skills}/technical_seo_checklist.md +0 -0
- /package/.agent/skills/tdd-master-workflow/{resources → sub-skills}/unit_test_naming_convention.md +0 -0
- /package/.agent/{.shared → skills}/ui-ux-pro-max/data/charts.csv +0 -0
- /package/.agent/{.shared → skills}/ui-ux-pro-max/data/prompts.csv +0 -0
- /package/.agent/{.shared → skills}/ui-ux-pro-max/data/styles.csv +0 -0
- /package/.agent/{.shared → skills}/ui-ux-pro-max/data/typography.csv +0 -0
- /package/.agent/{.shared → skills}/ui-ux-pro-max/data/ui-reasoning.csv +0 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Test: Distributed Task Queue Functionality
|
|
3
|
+
# Tests task creation, claiming, completion, and failure handling
|
|
4
|
+
|
|
5
|
+
set -uo pipefail
|
|
6
|
+
# Note: Not using -e to allow collecting all test results
|
|
7
|
+
|
|
8
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
|
+
TEST_DIR=$(mktemp -d)
|
|
10
|
+
PASSED=0
|
|
11
|
+
FAILED=0
|
|
12
|
+
|
|
13
|
+
# Colors
|
|
14
|
+
RED='\033[0;31m'
|
|
15
|
+
GREEN='\033[0;32m'
|
|
16
|
+
YELLOW='\033[1;33m'
|
|
17
|
+
NC='\033[0m'
|
|
18
|
+
|
|
19
|
+
log_pass() { echo -e "${GREEN}[PASS]${NC} $1"; ((PASSED++)); }
|
|
20
|
+
log_fail() { echo -e "${RED}[FAIL]${NC} $1"; ((FAILED++)); }
|
|
21
|
+
log_test() { echo -e "${YELLOW}[TEST]${NC} $1"; }
|
|
22
|
+
|
|
23
|
+
cleanup() {
|
|
24
|
+
rm -rf "$TEST_DIR"
|
|
25
|
+
}
|
|
26
|
+
trap cleanup EXIT
|
|
27
|
+
|
|
28
|
+
cd "$TEST_DIR"
|
|
29
|
+
|
|
30
|
+
echo "========================================"
|
|
31
|
+
echo "Loki Mode Task Queue Tests"
|
|
32
|
+
echo "========================================"
|
|
33
|
+
echo ""
|
|
34
|
+
|
|
35
|
+
# Initialize structure
|
|
36
|
+
mkdir -p .loki/{state/locks,queue}
|
|
37
|
+
for f in pending in-progress completed failed dead-letter; do
|
|
38
|
+
echo '{"tasks":[]}' > ".loki/queue/$f.json"
|
|
39
|
+
done
|
|
40
|
+
|
|
41
|
+
# Helper function to add task
|
|
42
|
+
add_task() {
|
|
43
|
+
local id="$1"
|
|
44
|
+
local type="$2"
|
|
45
|
+
local priority="${3:-5}"
|
|
46
|
+
|
|
47
|
+
local task=$(cat <<EOF
|
|
48
|
+
{
|
|
49
|
+
"id": "$id",
|
|
50
|
+
"type": "$type",
|
|
51
|
+
"priority": $priority,
|
|
52
|
+
"payload": {"action": "test"},
|
|
53
|
+
"createdAt": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
|
54
|
+
"claimedBy": null,
|
|
55
|
+
"claimedAt": null,
|
|
56
|
+
"timeout": 3600,
|
|
57
|
+
"retries": 0,
|
|
58
|
+
"maxRetries": 3
|
|
59
|
+
}
|
|
60
|
+
EOF
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# Add to pending queue
|
|
64
|
+
if command -v jq &> /dev/null; then
|
|
65
|
+
jq --argjson task "$task" '.tasks += [$task]' .loki/queue/pending.json > tmp.json && mv tmp.json .loki/queue/pending.json
|
|
66
|
+
else
|
|
67
|
+
# Fallback without jq
|
|
68
|
+
python3 -c "
|
|
69
|
+
import json
|
|
70
|
+
with open('.loki/queue/pending.json', 'r') as f:
|
|
71
|
+
data = json.load(f)
|
|
72
|
+
task = json.loads('''$task''')
|
|
73
|
+
data['tasks'].append(task)
|
|
74
|
+
with open('.loki/queue/pending.json', 'w') as f:
|
|
75
|
+
json.dump(data, f)
|
|
76
|
+
"
|
|
77
|
+
fi
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# Test 1: Add task to pending queue
|
|
81
|
+
log_test "Add task to pending queue"
|
|
82
|
+
add_task "task-001" "eng-backend" 5
|
|
83
|
+
|
|
84
|
+
task_count=$(python3 -c "import json; print(len(json.load(open('.loki/queue/pending.json'))['tasks']))")
|
|
85
|
+
if [ "$task_count" -eq 1 ]; then
|
|
86
|
+
log_pass "Task added to pending queue"
|
|
87
|
+
else
|
|
88
|
+
log_fail "Failed to add task (count: $task_count)"
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# Test 2: Add multiple tasks with priorities
|
|
92
|
+
log_test "Add multiple tasks with priorities"
|
|
93
|
+
add_task "task-002" "eng-frontend" 3
|
|
94
|
+
add_task "task-003" "eng-backend" 10
|
|
95
|
+
add_task "task-004" "ops-devops" 1
|
|
96
|
+
|
|
97
|
+
task_count=$(python3 -c "import json; print(len(json.load(open('.loki/queue/pending.json'))['tasks']))")
|
|
98
|
+
if [ "$task_count" -eq 4 ]; then
|
|
99
|
+
log_pass "Multiple tasks added"
|
|
100
|
+
else
|
|
101
|
+
log_fail "Failed to add multiple tasks (count: $task_count)"
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
# Test 3: Priority ordering
|
|
105
|
+
log_test "Priority ordering"
|
|
106
|
+
highest_priority=$(python3 -c "
|
|
107
|
+
import json
|
|
108
|
+
data = json.load(open('.loki/queue/pending.json'))
|
|
109
|
+
sorted_tasks = sorted(data['tasks'], key=lambda t: -t['priority'])
|
|
110
|
+
print(sorted_tasks[0]['id'])
|
|
111
|
+
")
|
|
112
|
+
|
|
113
|
+
if [ "$highest_priority" = "task-003" ]; then
|
|
114
|
+
log_pass "Highest priority task is task-003 (priority 10)"
|
|
115
|
+
else
|
|
116
|
+
log_fail "Priority ordering wrong: got $highest_priority, expected task-003"
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
# Test 4: Claim task (atomic operation simulation)
|
|
120
|
+
log_test "Claim task atomically"
|
|
121
|
+
python3 << 'EOF'
|
|
122
|
+
import json
|
|
123
|
+
import os
|
|
124
|
+
from datetime import datetime
|
|
125
|
+
|
|
126
|
+
# Simulate atomic claim with file locking
|
|
127
|
+
queue_file = '.loki/queue/pending.json'
|
|
128
|
+
progress_file = '.loki/queue/in-progress.json'
|
|
129
|
+
lock_file = '.loki/state/locks/queue.lock'
|
|
130
|
+
|
|
131
|
+
# Read pending
|
|
132
|
+
with open(queue_file, 'r') as f:
|
|
133
|
+
pending = json.load(f)
|
|
134
|
+
|
|
135
|
+
# Find highest priority unclaimed task
|
|
136
|
+
tasks = sorted(pending['tasks'], key=lambda t: -t['priority'])
|
|
137
|
+
claimed_task = None
|
|
138
|
+
for task in tasks:
|
|
139
|
+
if task.get('claimedBy') is None:
|
|
140
|
+
task['claimedBy'] = 'agent-001'
|
|
141
|
+
task['claimedAt'] = datetime.utcnow().isoformat() + 'Z'
|
|
142
|
+
claimed_task = task
|
|
143
|
+
break
|
|
144
|
+
|
|
145
|
+
if claimed_task:
|
|
146
|
+
# Remove from pending
|
|
147
|
+
pending['tasks'] = [t for t in pending['tasks'] if t['id'] != claimed_task['id']]
|
|
148
|
+
|
|
149
|
+
# Add to in-progress
|
|
150
|
+
with open(progress_file, 'r') as f:
|
|
151
|
+
progress = json.load(f)
|
|
152
|
+
progress['tasks'].append(claimed_task)
|
|
153
|
+
|
|
154
|
+
# Write both files
|
|
155
|
+
with open(queue_file, 'w') as f:
|
|
156
|
+
json.dump(pending, f)
|
|
157
|
+
with open(progress_file, 'w') as f:
|
|
158
|
+
json.dump(progress, f)
|
|
159
|
+
|
|
160
|
+
print(f"CLAIMED:{claimed_task['id']}")
|
|
161
|
+
else:
|
|
162
|
+
print("NONE")
|
|
163
|
+
EOF
|
|
164
|
+
|
|
165
|
+
claimed=$(python3 -c "
|
|
166
|
+
import json
|
|
167
|
+
data = json.load(open('.loki/queue/in-progress.json'))
|
|
168
|
+
if data['tasks']:
|
|
169
|
+
print(data['tasks'][0]['id'])
|
|
170
|
+
else:
|
|
171
|
+
print('NONE')
|
|
172
|
+
")
|
|
173
|
+
|
|
174
|
+
if [ "$claimed" = "task-003" ]; then
|
|
175
|
+
log_pass "Claimed highest priority task (task-003)"
|
|
176
|
+
else
|
|
177
|
+
log_fail "Claim failed: got $claimed"
|
|
178
|
+
fi
|
|
179
|
+
|
|
180
|
+
# Test 5: Complete task
|
|
181
|
+
log_test "Complete task"
|
|
182
|
+
python3 << 'EOF'
|
|
183
|
+
import json
|
|
184
|
+
from datetime import datetime
|
|
185
|
+
|
|
186
|
+
progress_file = '.loki/queue/in-progress.json'
|
|
187
|
+
completed_file = '.loki/queue/completed.json'
|
|
188
|
+
|
|
189
|
+
with open(progress_file, 'r') as f:
|
|
190
|
+
progress = json.load(f)
|
|
191
|
+
|
|
192
|
+
with open(completed_file, 'r') as f:
|
|
193
|
+
completed = json.load(f)
|
|
194
|
+
|
|
195
|
+
# Complete first task
|
|
196
|
+
if progress['tasks']:
|
|
197
|
+
task = progress['tasks'][0]
|
|
198
|
+
task['completedAt'] = datetime.utcnow().isoformat() + 'Z'
|
|
199
|
+
task['result'] = {'status': 'success'}
|
|
200
|
+
|
|
201
|
+
completed['tasks'].append(task)
|
|
202
|
+
progress['tasks'] = progress['tasks'][1:]
|
|
203
|
+
|
|
204
|
+
with open(progress_file, 'w') as f:
|
|
205
|
+
json.dump(progress, f)
|
|
206
|
+
with open(completed_file, 'w') as f:
|
|
207
|
+
json.dump(completed, f)
|
|
208
|
+
|
|
209
|
+
print("COMPLETED")
|
|
210
|
+
EOF
|
|
211
|
+
|
|
212
|
+
completed_count=$(python3 -c "import json; print(len(json.load(open('.loki/queue/completed.json'))['tasks']))")
|
|
213
|
+
if [ "$completed_count" -eq 1 ]; then
|
|
214
|
+
log_pass "Task completed successfully"
|
|
215
|
+
else
|
|
216
|
+
log_fail "Task completion failed"
|
|
217
|
+
fi
|
|
218
|
+
|
|
219
|
+
# Test 6: Fail task with retry
|
|
220
|
+
log_test "Fail task with retry"
|
|
221
|
+
# First claim a task
|
|
222
|
+
python3 << 'EOF'
|
|
223
|
+
import json
|
|
224
|
+
from datetime import datetime
|
|
225
|
+
|
|
226
|
+
queue_file = '.loki/queue/pending.json'
|
|
227
|
+
progress_file = '.loki/queue/in-progress.json'
|
|
228
|
+
|
|
229
|
+
with open(queue_file, 'r') as f:
|
|
230
|
+
pending = json.load(f)
|
|
231
|
+
|
|
232
|
+
if pending['tasks']:
|
|
233
|
+
task = pending['tasks'][0]
|
|
234
|
+
task['claimedBy'] = 'agent-002'
|
|
235
|
+
task['claimedAt'] = datetime.utcnow().isoformat() + 'Z'
|
|
236
|
+
|
|
237
|
+
with open(progress_file, 'r') as f:
|
|
238
|
+
progress = json.load(f)
|
|
239
|
+
|
|
240
|
+
progress['tasks'].append(task)
|
|
241
|
+
pending['tasks'] = pending['tasks'][1:]
|
|
242
|
+
|
|
243
|
+
with open(queue_file, 'w') as f:
|
|
244
|
+
json.dump(pending, f)
|
|
245
|
+
with open(progress_file, 'w') as f:
|
|
246
|
+
json.dump(progress, f)
|
|
247
|
+
EOF
|
|
248
|
+
|
|
249
|
+
# Now fail it
|
|
250
|
+
python3 << 'EOF'
|
|
251
|
+
import json
|
|
252
|
+
from datetime import datetime
|
|
253
|
+
|
|
254
|
+
progress_file = '.loki/queue/in-progress.json'
|
|
255
|
+
pending_file = '.loki/queue/pending.json'
|
|
256
|
+
|
|
257
|
+
with open(progress_file, 'r') as f:
|
|
258
|
+
progress = json.load(f)
|
|
259
|
+
|
|
260
|
+
if progress['tasks']:
|
|
261
|
+
task = progress['tasks'][0]
|
|
262
|
+
task['retries'] = task.get('retries', 0) + 1
|
|
263
|
+
task['lastError'] = 'Test failure'
|
|
264
|
+
task['claimedBy'] = None
|
|
265
|
+
task['claimedAt'] = None
|
|
266
|
+
task['backoffSeconds'] = 60 * (2 ** (task['retries'] - 1))
|
|
267
|
+
|
|
268
|
+
# Move back to pending for retry
|
|
269
|
+
with open(pending_file, 'r') as f:
|
|
270
|
+
pending = json.load(f)
|
|
271
|
+
|
|
272
|
+
pending['tasks'].append(task)
|
|
273
|
+
progress['tasks'] = progress['tasks'][1:]
|
|
274
|
+
|
|
275
|
+
with open(progress_file, 'w') as f:
|
|
276
|
+
json.dump(progress, f)
|
|
277
|
+
with open(pending_file, 'w') as f:
|
|
278
|
+
json.dump(pending, f)
|
|
279
|
+
|
|
280
|
+
print(f"RETRY:{task['retries']}")
|
|
281
|
+
EOF
|
|
282
|
+
|
|
283
|
+
retry_count=$(python3 -c "
|
|
284
|
+
import json
|
|
285
|
+
data = json.load(open('.loki/queue/pending.json'))
|
|
286
|
+
for t in data['tasks']:
|
|
287
|
+
if t.get('retries', 0) > 0:
|
|
288
|
+
print(t['retries'])
|
|
289
|
+
break
|
|
290
|
+
else:
|
|
291
|
+
print(0)
|
|
292
|
+
")
|
|
293
|
+
|
|
294
|
+
if [ "$retry_count" -eq 1 ]; then
|
|
295
|
+
log_pass "Task moved back to pending with retry count"
|
|
296
|
+
else
|
|
297
|
+
log_fail "Retry handling failed"
|
|
298
|
+
fi
|
|
299
|
+
|
|
300
|
+
# Test 7: Dead letter queue
|
|
301
|
+
log_test "Move to dead letter queue after max retries"
|
|
302
|
+
python3 << 'EOF'
|
|
303
|
+
import json
|
|
304
|
+
from datetime import datetime
|
|
305
|
+
|
|
306
|
+
pending_file = '.loki/queue/pending.json'
|
|
307
|
+
dlq_file = '.loki/queue/dead-letter.json'
|
|
308
|
+
|
|
309
|
+
with open(pending_file, 'r') as f:
|
|
310
|
+
pending = json.load(f)
|
|
311
|
+
|
|
312
|
+
with open(dlq_file, 'r') as f:
|
|
313
|
+
dlq = json.load(f)
|
|
314
|
+
|
|
315
|
+
# Find task with retries and simulate max retries exceeded
|
|
316
|
+
for task in pending['tasks']:
|
|
317
|
+
if task.get('retries', 0) > 0:
|
|
318
|
+
task['retries'] = task.get('maxRetries', 3)
|
|
319
|
+
task['lastError'] = 'Max retries exceeded'
|
|
320
|
+
task['movedToDLQ'] = datetime.utcnow().isoformat() + 'Z'
|
|
321
|
+
|
|
322
|
+
dlq['tasks'].append(task)
|
|
323
|
+
pending['tasks'] = [t for t in pending['tasks'] if t['id'] != task['id']]
|
|
324
|
+
break
|
|
325
|
+
|
|
326
|
+
with open(pending_file, 'w') as f:
|
|
327
|
+
json.dump(pending, f)
|
|
328
|
+
with open(dlq_file, 'w') as f:
|
|
329
|
+
json.dump(dlq, f)
|
|
330
|
+
|
|
331
|
+
print("MOVED_TO_DLQ")
|
|
332
|
+
EOF
|
|
333
|
+
|
|
334
|
+
dlq_count=$(python3 -c "import json; print(len(json.load(open('.loki/queue/dead-letter.json'))['tasks']))")
|
|
335
|
+
if [ "$dlq_count" -eq 1 ]; then
|
|
336
|
+
log_pass "Task moved to dead letter queue"
|
|
337
|
+
else
|
|
338
|
+
log_fail "Dead letter queue handling failed"
|
|
339
|
+
fi
|
|
340
|
+
|
|
341
|
+
# Test 8: Idempotency check
|
|
342
|
+
log_test "Idempotency check (duplicate prevention)"
|
|
343
|
+
python3 << 'EOF'
|
|
344
|
+
import json
|
|
345
|
+
import hashlib
|
|
346
|
+
|
|
347
|
+
pending_file = '.loki/queue/pending.json'
|
|
348
|
+
|
|
349
|
+
with open(pending_file, 'r') as f:
|
|
350
|
+
pending = json.load(f)
|
|
351
|
+
|
|
352
|
+
# Try to add duplicate task
|
|
353
|
+
new_task = {
|
|
354
|
+
"id": "task-duplicate",
|
|
355
|
+
"type": "eng-backend",
|
|
356
|
+
"payload": {"action": "test"}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
# Generate idempotency key
|
|
360
|
+
idempotency_key = hashlib.md5(json.dumps(new_task['payload'], sort_keys=True).encode()).hexdigest()
|
|
361
|
+
new_task['idempotencyKey'] = idempotency_key
|
|
362
|
+
|
|
363
|
+
# Check if already exists
|
|
364
|
+
existing = [t for t in pending['tasks'] if t.get('idempotencyKey') == idempotency_key]
|
|
365
|
+
if not existing:
|
|
366
|
+
pending['tasks'].append(new_task)
|
|
367
|
+
print("ADDED")
|
|
368
|
+
else:
|
|
369
|
+
print("DUPLICATE")
|
|
370
|
+
|
|
371
|
+
# Try again with same payload
|
|
372
|
+
existing = [t for t in pending['tasks'] if t.get('idempotencyKey') == idempotency_key]
|
|
373
|
+
if existing:
|
|
374
|
+
print("DUPLICATE_DETECTED")
|
|
375
|
+
|
|
376
|
+
with open(pending_file, 'w') as f:
|
|
377
|
+
json.dump(pending, f)
|
|
378
|
+
EOF
|
|
379
|
+
|
|
380
|
+
log_pass "Idempotency check works"
|
|
381
|
+
|
|
382
|
+
echo ""
|
|
383
|
+
echo "========================================"
|
|
384
|
+
echo "Test Summary"
|
|
385
|
+
echo "========================================"
|
|
386
|
+
echo -e "${GREEN}Passed: $PASSED${NC}"
|
|
387
|
+
echo -e "${RED}Failed: $FAILED${NC}"
|
|
388
|
+
echo ""
|
|
389
|
+
|
|
390
|
+
if [ $FAILED -eq 0 ]; then
|
|
391
|
+
echo -e "${GREEN}All tests passed!${NC}"
|
|
392
|
+
exit 0
|
|
393
|
+
else
|
|
394
|
+
echo -e "${RED}Some tests failed!${NC}"
|
|
395
|
+
exit 1
|
|
396
|
+
fi
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Test: Loki Mode Wrapper Script
|
|
3
|
+
# Tests the autonomous wrapper functionality
|
|
4
|
+
|
|
5
|
+
set -uo pipefail
|
|
6
|
+
|
|
7
|
+
TEST_DIR=$(mktemp -d)
|
|
8
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
|
+
WRAPPER_SCRIPT="$SCRIPT_DIR/../scripts/loki-wrapper.sh"
|
|
10
|
+
PASSED=0
|
|
11
|
+
FAILED=0
|
|
12
|
+
|
|
13
|
+
# Colors
|
|
14
|
+
RED='\033[0;31m'
|
|
15
|
+
GREEN='\033[0;32m'
|
|
16
|
+
YELLOW='\033[1;33m'
|
|
17
|
+
NC='\033[0m'
|
|
18
|
+
|
|
19
|
+
log_pass() { echo -e "${GREEN}[PASS]${NC} $1"; ((PASSED++)); }
|
|
20
|
+
log_fail() { echo -e "${RED}[FAIL]${NC} $1"; ((FAILED++)); }
|
|
21
|
+
log_test() { echo -e "${YELLOW}[TEST]${NC} $1"; }
|
|
22
|
+
|
|
23
|
+
cleanup() {
|
|
24
|
+
rm -rf "$TEST_DIR"
|
|
25
|
+
}
|
|
26
|
+
trap cleanup EXIT
|
|
27
|
+
|
|
28
|
+
cd "$TEST_DIR"
|
|
29
|
+
|
|
30
|
+
echo "=========================================="
|
|
31
|
+
echo "Loki Mode Wrapper Script Tests"
|
|
32
|
+
echo "=========================================="
|
|
33
|
+
echo ""
|
|
34
|
+
|
|
35
|
+
# Test 1: Wrapper script exists and is executable
|
|
36
|
+
log_test "Wrapper script exists and is executable"
|
|
37
|
+
if [ -x "$WRAPPER_SCRIPT" ]; then
|
|
38
|
+
log_pass "Wrapper script is executable"
|
|
39
|
+
else
|
|
40
|
+
log_fail "Wrapper script not found or not executable"
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# Test 2: Wrapper script has correct shebang
|
|
44
|
+
log_test "Wrapper script has correct shebang"
|
|
45
|
+
SHEBANG=$(head -1 "$WRAPPER_SCRIPT")
|
|
46
|
+
if [ "$SHEBANG" = "#!/bin/bash" ]; then
|
|
47
|
+
log_pass "Correct shebang"
|
|
48
|
+
else
|
|
49
|
+
log_fail "Incorrect shebang: $SHEBANG"
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# Test 3: Exponential backoff calculation
|
|
53
|
+
log_test "Exponential backoff calculation"
|
|
54
|
+
python3 << 'EOF'
|
|
55
|
+
import os
|
|
56
|
+
|
|
57
|
+
BASE_WAIT = 60
|
|
58
|
+
MAX_WAIT = 3600
|
|
59
|
+
|
|
60
|
+
def calculate_wait(retry):
|
|
61
|
+
wait_time = BASE_WAIT * (2 ** retry)
|
|
62
|
+
# Add jitter would be random, just test base calculation
|
|
63
|
+
if wait_time > MAX_WAIT:
|
|
64
|
+
wait_time = MAX_WAIT
|
|
65
|
+
return wait_time
|
|
66
|
+
|
|
67
|
+
# Test exponential growth
|
|
68
|
+
assert calculate_wait(0) == 60, f"Retry 0: expected 60, got {calculate_wait(0)}"
|
|
69
|
+
assert calculate_wait(1) == 120, f"Retry 1: expected 120, got {calculate_wait(1)}"
|
|
70
|
+
assert calculate_wait(2) == 240, f"Retry 2: expected 240, got {calculate_wait(2)}"
|
|
71
|
+
assert calculate_wait(3) == 480, f"Retry 3: expected 480, got {calculate_wait(3)}"
|
|
72
|
+
assert calculate_wait(4) == 960, f"Retry 4: expected 960, got {calculate_wait(4)}"
|
|
73
|
+
assert calculate_wait(5) == 1920, f"Retry 5: expected 1920, got {calculate_wait(5)}"
|
|
74
|
+
|
|
75
|
+
# Test max cap
|
|
76
|
+
assert calculate_wait(6) == 3600, f"Retry 6: expected 3600 (capped), got {calculate_wait(6)}"
|
|
77
|
+
assert calculate_wait(10) == 3600, f"Retry 10: expected 3600 (capped), got {calculate_wait(10)}"
|
|
78
|
+
|
|
79
|
+
print("VERIFIED")
|
|
80
|
+
EOF
|
|
81
|
+
|
|
82
|
+
if [ $? -eq 0 ]; then
|
|
83
|
+
log_pass "Exponential backoff calculation works"
|
|
84
|
+
else
|
|
85
|
+
log_fail "Exponential backoff calculation failed"
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
# Test 4: State file JSON structure
|
|
89
|
+
log_test "State file JSON structure"
|
|
90
|
+
python3 << 'EOF'
|
|
91
|
+
import json
|
|
92
|
+
from datetime import datetime
|
|
93
|
+
|
|
94
|
+
# Simulate wrapper state
|
|
95
|
+
state = {
|
|
96
|
+
"retryCount": 3,
|
|
97
|
+
"status": "running",
|
|
98
|
+
"lastExitCode": 0,
|
|
99
|
+
"lastRun": datetime.utcnow().isoformat() + 'Z',
|
|
100
|
+
"prdPath": "./docs/requirements.md",
|
|
101
|
+
"pid": 12345
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
# Verify JSON serialization
|
|
105
|
+
json_str = json.dumps(state)
|
|
106
|
+
parsed = json.loads(json_str)
|
|
107
|
+
|
|
108
|
+
assert parsed["retryCount"] == 3
|
|
109
|
+
assert parsed["status"] == "running"
|
|
110
|
+
assert parsed["pid"] == 12345
|
|
111
|
+
print("VERIFIED")
|
|
112
|
+
EOF
|
|
113
|
+
|
|
114
|
+
if [ $? -eq 0 ]; then
|
|
115
|
+
log_pass "State file JSON structure is valid"
|
|
116
|
+
else
|
|
117
|
+
log_fail "State file JSON structure failed"
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
# Test 5: Completion detection logic
|
|
121
|
+
log_test "Completion detection logic"
|
|
122
|
+
mkdir -p "$TEST_DIR/.loki/state"
|
|
123
|
+
cat > "$TEST_DIR/.loki/state/orchestrator.json" << 'EOF'
|
|
124
|
+
{
|
|
125
|
+
"currentPhase": "COMPLETED",
|
|
126
|
+
"startedAt": "2025-01-15T10:00:00Z",
|
|
127
|
+
"completedAt": "2025-01-15T12:00:00Z"
|
|
128
|
+
}
|
|
129
|
+
EOF
|
|
130
|
+
|
|
131
|
+
python3 << EOF
|
|
132
|
+
import json
|
|
133
|
+
|
|
134
|
+
with open("$TEST_DIR/.loki/state/orchestrator.json") as f:
|
|
135
|
+
state = json.load(f)
|
|
136
|
+
|
|
137
|
+
phase = state.get("currentPhase", "")
|
|
138
|
+
is_completed = phase == "COMPLETED"
|
|
139
|
+
assert is_completed, f"Expected COMPLETED, got {phase}"
|
|
140
|
+
print("VERIFIED")
|
|
141
|
+
EOF
|
|
142
|
+
|
|
143
|
+
if [ $? -eq 0 ]; then
|
|
144
|
+
log_pass "Completion detection works"
|
|
145
|
+
else
|
|
146
|
+
log_fail "Completion detection failed"
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
# Test 6: PRD path validation
|
|
150
|
+
log_test "PRD path validation"
|
|
151
|
+
touch "$TEST_DIR/test-prd.md"
|
|
152
|
+
if [ -f "$TEST_DIR/test-prd.md" ]; then
|
|
153
|
+
log_pass "PRD path validation works"
|
|
154
|
+
else
|
|
155
|
+
log_fail "PRD path validation failed"
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
# Test 7: Resume prompt generation
|
|
159
|
+
log_test "Resume prompt generation"
|
|
160
|
+
python3 << 'EOF'
|
|
161
|
+
def build_resume_prompt(retry, prd_path=None, initial_prompt="Loki Mode"):
|
|
162
|
+
if retry == 0:
|
|
163
|
+
return initial_prompt
|
|
164
|
+
else:
|
|
165
|
+
if prd_path:
|
|
166
|
+
return f"Loki Mode - Resume from checkpoint. PRD at {prd_path}. This is retry #{retry} after rate limit. Check .loki/state/ for current progress and continue from where we left off."
|
|
167
|
+
else:
|
|
168
|
+
return f"Loki Mode - Resume from checkpoint. This is retry #{retry} after rate limit. Check .loki/state/ for current progress and continue from where we left off."
|
|
169
|
+
|
|
170
|
+
# Test initial prompt
|
|
171
|
+
assert build_resume_prompt(0) == "Loki Mode"
|
|
172
|
+
|
|
173
|
+
# Test resume prompt without PRD
|
|
174
|
+
resume = build_resume_prompt(3)
|
|
175
|
+
assert "Resume from checkpoint" in resume
|
|
176
|
+
assert "retry #3" in resume
|
|
177
|
+
assert ".loki/state/" in resume
|
|
178
|
+
|
|
179
|
+
# Test resume prompt with PRD
|
|
180
|
+
resume = build_resume_prompt(5, "./docs/req.md")
|
|
181
|
+
assert "PRD at ./docs/req.md" in resume
|
|
182
|
+
assert "retry #5" in resume
|
|
183
|
+
|
|
184
|
+
print("VERIFIED")
|
|
185
|
+
EOF
|
|
186
|
+
|
|
187
|
+
if [ $? -eq 0 ]; then
|
|
188
|
+
log_pass "Resume prompt generation works"
|
|
189
|
+
else
|
|
190
|
+
log_fail "Resume prompt generation failed"
|
|
191
|
+
fi
|
|
192
|
+
|
|
193
|
+
# Test 8: Rate limit detection logic
|
|
194
|
+
log_test "Rate limit detection logic"
|
|
195
|
+
python3 << 'EOF'
|
|
196
|
+
def is_rate_limit(exit_code, log_content=""):
|
|
197
|
+
# Any non-zero exit is treated as potential rate limit
|
|
198
|
+
if exit_code != 0:
|
|
199
|
+
# Could check logs for specific indicators
|
|
200
|
+
rate_limit_indicators = ["rate limit", "429", "too many requests", "quota exceeded"]
|
|
201
|
+
for indicator in rate_limit_indicators:
|
|
202
|
+
if indicator.lower() in log_content.lower():
|
|
203
|
+
return True
|
|
204
|
+
# Conservative: treat any non-zero as rate limit
|
|
205
|
+
return True
|
|
206
|
+
return False
|
|
207
|
+
|
|
208
|
+
# Test cases
|
|
209
|
+
assert is_rate_limit(0) == False, "Exit 0 should not be rate limit"
|
|
210
|
+
assert is_rate_limit(1) == True, "Exit 1 should be treated as rate limit"
|
|
211
|
+
assert is_rate_limit(1, "Error: Rate limit exceeded") == True
|
|
212
|
+
assert is_rate_limit(1, "HTTP 429 Too Many Requests") == True
|
|
213
|
+
assert is_rate_limit(0, "Rate limit in logs but exit 0") == False
|
|
214
|
+
|
|
215
|
+
print("VERIFIED")
|
|
216
|
+
EOF
|
|
217
|
+
|
|
218
|
+
if [ $? -eq 0 ]; then
|
|
219
|
+
log_pass "Rate limit detection logic works"
|
|
220
|
+
else
|
|
221
|
+
log_fail "Rate limit detection logic failed"
|
|
222
|
+
fi
|
|
223
|
+
|
|
224
|
+
# Test 9: Log file creation
|
|
225
|
+
log_test "Log file and directory creation"
|
|
226
|
+
mkdir -p "$TEST_DIR/.loki"
|
|
227
|
+
LOG_FILE="$TEST_DIR/.loki/wrapper.log"
|
|
228
|
+
echo "[2025-01-15 10:00:00] [INFO] Test log entry" >> "$LOG_FILE"
|
|
229
|
+
|
|
230
|
+
if [ -f "$LOG_FILE" ] && grep -q "Test log entry" "$LOG_FILE"; then
|
|
231
|
+
log_pass "Log file creation works"
|
|
232
|
+
else
|
|
233
|
+
log_fail "Log file creation failed"
|
|
234
|
+
fi
|
|
235
|
+
|
|
236
|
+
# Test 10: COMPLETED file marker detection
|
|
237
|
+
log_test "COMPLETED file marker detection"
|
|
238
|
+
touch "$TEST_DIR/.loki/COMPLETED"
|
|
239
|
+
if [ -f "$TEST_DIR/.loki/COMPLETED" ]; then
|
|
240
|
+
log_pass "COMPLETED file marker detection works"
|
|
241
|
+
else
|
|
242
|
+
log_fail "COMPLETED file marker detection failed"
|
|
243
|
+
fi
|
|
244
|
+
|
|
245
|
+
# Test 11: Environment variable defaults
|
|
246
|
+
log_test "Environment variable defaults"
|
|
247
|
+
python3 << 'EOF'
|
|
248
|
+
import os
|
|
249
|
+
|
|
250
|
+
# Simulate reading with defaults
|
|
251
|
+
MAX_RETRIES = int(os.environ.get('LOKI_MAX_RETRIES', '50'))
|
|
252
|
+
BASE_WAIT = int(os.environ.get('LOKI_BASE_WAIT', '60'))
|
|
253
|
+
MAX_WAIT = int(os.environ.get('LOKI_MAX_WAIT', '3600'))
|
|
254
|
+
|
|
255
|
+
assert MAX_RETRIES == 50, f"Expected 50, got {MAX_RETRIES}"
|
|
256
|
+
assert BASE_WAIT == 60, f"Expected 60, got {BASE_WAIT}"
|
|
257
|
+
assert MAX_WAIT == 3600, f"Expected 3600, got {MAX_WAIT}"
|
|
258
|
+
|
|
259
|
+
print("VERIFIED")
|
|
260
|
+
EOF
|
|
261
|
+
|
|
262
|
+
if [ $? -eq 0 ]; then
|
|
263
|
+
log_pass "Environment variable defaults work"
|
|
264
|
+
else
|
|
265
|
+
log_fail "Environment variable defaults failed"
|
|
266
|
+
fi
|
|
267
|
+
|
|
268
|
+
# Test 12: Wrapper state loading
|
|
269
|
+
log_test "Wrapper state loading and saving"
|
|
270
|
+
STATE_FILE="$TEST_DIR/.loki/wrapper-state.json"
|
|
271
|
+
cat > "$STATE_FILE" << 'EOF'
|
|
272
|
+
{
|
|
273
|
+
"retryCount": 7,
|
|
274
|
+
"status": "running",
|
|
275
|
+
"lastExitCode": 1,
|
|
276
|
+
"lastRun": "2025-01-15T10:30:00Z",
|
|
277
|
+
"prdPath": "./test.md",
|
|
278
|
+
"pid": 99999
|
|
279
|
+
}
|
|
280
|
+
EOF
|
|
281
|
+
|
|
282
|
+
python3 << EOF
|
|
283
|
+
import json
|
|
284
|
+
|
|
285
|
+
with open("$STATE_FILE") as f:
|
|
286
|
+
state = json.load(f)
|
|
287
|
+
|
|
288
|
+
assert state["retryCount"] == 7
|
|
289
|
+
assert state["status"] == "running"
|
|
290
|
+
assert state["lastExitCode"] == 1
|
|
291
|
+
print("VERIFIED")
|
|
292
|
+
EOF
|
|
293
|
+
|
|
294
|
+
if [ $? -eq 0 ]; then
|
|
295
|
+
log_pass "Wrapper state loading works"
|
|
296
|
+
else
|
|
297
|
+
log_fail "Wrapper state loading failed"
|
|
298
|
+
fi
|
|
299
|
+
|
|
300
|
+
echo ""
|
|
301
|
+
echo "=========================================="
|
|
302
|
+
echo "Test Summary"
|
|
303
|
+
echo "=========================================="
|
|
304
|
+
echo -e "${GREEN}Passed: $PASSED${NC}"
|
|
305
|
+
echo -e "${RED}Failed: $FAILED${NC}"
|
|
306
|
+
echo ""
|
|
307
|
+
|
|
308
|
+
if [ $FAILED -eq 0 ]; then
|
|
309
|
+
echo -e "${GREEN}All tests passed!${NC}"
|
|
310
|
+
exit 0
|
|
311
|
+
else
|
|
312
|
+
echo -e "${RED}Some tests failed!${NC}"
|
|
313
|
+
exit 1
|
|
314
|
+
fi
|