arkaos 2.0.0-alpha.1
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/CONSTITUTION.md +81 -0
- package/LICENSE +21 -0
- package/README.md +154 -0
- package/VERSION +1 -0
- package/arka/SKILL.md +134 -0
- package/bin/arkaos +107 -0
- package/config/constitution.yaml +168 -0
- package/config/hooks/post-tool-use-v2.sh +116 -0
- package/config/hooks/post-tool-use.sh +188 -0
- package/config/hooks/pre-compact-v2.sh +43 -0
- package/config/hooks/pre-compact.sh +99 -0
- package/config/hooks/user-prompt-submit-v2.sh +119 -0
- package/config/hooks/user-prompt-submit.sh +312 -0
- package/core/__init__.py +3 -0
- package/core/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/agents/__init__.py +14 -0
- package/core/agents/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/agents/__pycache__/loader.cpython-313.pyc +0 -0
- package/core/agents/__pycache__/registry_gen.cpython-313.pyc +0 -0
- package/core/agents/__pycache__/schema.cpython-313.pyc +0 -0
- package/core/agents/__pycache__/validator.cpython-313.pyc +0 -0
- package/core/agents/loader.py +88 -0
- package/core/agents/registry_gen.py +118 -0
- package/core/agents/schema.py +265 -0
- package/core/agents/validator.py +141 -0
- package/core/conclave/__init__.py +12 -0
- package/core/conclave/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/conclave/__pycache__/advisor_db.cpython-313.pyc +0 -0
- package/core/conclave/__pycache__/display.cpython-313.pyc +0 -0
- package/core/conclave/__pycache__/matcher.cpython-313.pyc +0 -0
- package/core/conclave/__pycache__/persistence.cpython-313.pyc +0 -0
- package/core/conclave/__pycache__/profiler.cpython-313.pyc +0 -0
- package/core/conclave/__pycache__/prompts.cpython-313.pyc +0 -0
- package/core/conclave/__pycache__/schema.cpython-313.pyc +0 -0
- package/core/conclave/advisor_db.py +373 -0
- package/core/conclave/display.py +104 -0
- package/core/conclave/matcher.py +104 -0
- package/core/conclave/persistence.py +61 -0
- package/core/conclave/profiler.py +298 -0
- package/core/conclave/prompts.py +77 -0
- package/core/conclave/schema.py +132 -0
- package/core/governance/__init__.py +5 -0
- package/core/governance/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/governance/__pycache__/constitution.cpython-313.pyc +0 -0
- package/core/governance/constitution.py +152 -0
- package/core/registry/__init__.py +1 -0
- package/core/registry/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/registry/__pycache__/generator.cpython-313.pyc +0 -0
- package/core/registry/generator.py +199 -0
- package/core/runtime/__init__.py +6 -0
- package/core/runtime/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/base.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/claude_code.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/codex_cli.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/cursor.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/gemini_cli.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/registry.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/subagent.cpython-313.pyc +0 -0
- package/core/runtime/base.py +143 -0
- package/core/runtime/claude_code.py +104 -0
- package/core/runtime/codex_cli.py +71 -0
- package/core/runtime/cursor.py +71 -0
- package/core/runtime/gemini_cli.py +68 -0
- package/core/runtime/registry.py +86 -0
- package/core/runtime/subagent.py +201 -0
- package/core/specs/__init__.py +10 -0
- package/core/specs/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/specs/__pycache__/manager.cpython-313.pyc +0 -0
- package/core/specs/__pycache__/schema.cpython-313.pyc +0 -0
- package/core/specs/manager.py +164 -0
- package/core/specs/schema.py +199 -0
- package/core/squads/__init__.py +7 -0
- package/core/squads/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/squads/__pycache__/loader.cpython-313.pyc +0 -0
- package/core/squads/__pycache__/registry.cpython-313.pyc +0 -0
- package/core/squads/__pycache__/schema.cpython-313.pyc +0 -0
- package/core/squads/loader.py +40 -0
- package/core/squads/registry.py +145 -0
- package/core/squads/schema.py +93 -0
- package/core/synapse/__init__.py +11 -0
- package/core/synapse/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/synapse/__pycache__/cache.cpython-313.pyc +0 -0
- package/core/synapse/__pycache__/engine.cpython-313.pyc +0 -0
- package/core/synapse/__pycache__/layers.cpython-313.pyc +0 -0
- package/core/synapse/cache.py +82 -0
- package/core/synapse/engine.py +184 -0
- package/core/synapse/layers.py +441 -0
- package/core/tasks/__init__.py +6 -0
- package/core/tasks/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/tasks/__pycache__/manager.cpython-313.pyc +0 -0
- package/core/tasks/__pycache__/schema.cpython-313.pyc +0 -0
- package/core/tasks/manager.py +150 -0
- package/core/tasks/schema.py +108 -0
- package/core/workflow/__init__.py +10 -0
- package/core/workflow/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/workflow/__pycache__/engine.cpython-313.pyc +0 -0
- package/core/workflow/__pycache__/loader.cpython-313.pyc +0 -0
- package/core/workflow/__pycache__/schema.cpython-313.pyc +0 -0
- package/core/workflow/engine.py +216 -0
- package/core/workflow/loader.py +28 -0
- package/core/workflow/schema.py +129 -0
- package/departments/brand/SKILL.md +85 -0
- package/departments/brand/agents/brand-director.yaml +77 -0
- package/departments/brand/agents/brand-strategist.md +182 -0
- package/departments/brand/agents/brand-strategist.yaml +58 -0
- package/departments/brand/agents/creative-director.md +149 -0
- package/departments/brand/agents/motion-designer.md +113 -0
- package/departments/brand/agents/ux-designer.yaml +60 -0
- package/departments/brand/agents/visual-designer.md +187 -0
- package/departments/brand/agents/visual-designer.yaml +58 -0
- package/departments/brand/references/brand-creation-guide.md +559 -0
- package/departments/brand/scripts/provider-call.sh +262 -0
- package/departments/brand/skills/archetype-finder/SKILL.md +18 -0
- package/departments/brand/skills/colors/SKILL.md +18 -0
- package/departments/brand/skills/design-system/SKILL.md +18 -0
- package/departments/brand/skills/identity-system/SKILL.md +18 -0
- package/departments/brand/skills/logo-brief/SKILL.md +18 -0
- package/departments/brand/skills/mockup-generate/SKILL.md +18 -0
- package/departments/brand/skills/naming-evaluate/SKILL.md +50 -0
- package/departments/brand/skills/positioning-statement/SKILL.md +18 -0
- package/departments/brand/skills/primal-audit/SKILL.md +43 -0
- package/departments/brand/skills/ux-audit/SKILL.md +18 -0
- package/departments/brand/skills/voice-guide/SKILL.md +18 -0
- package/departments/brand/skills/wireframe/SKILL.md +18 -0
- package/departments/brand/squad.yaml +39 -0
- package/departments/brand/workflows/identity.yaml +113 -0
- package/departments/brand/workflows/naming.yaml +58 -0
- package/departments/community/SKILL.md +62 -0
- package/departments/community/agents/community-manager.yaml +57 -0
- package/departments/community/agents/community-strategist.yaml +74 -0
- package/departments/community/agents/engagement-designer.yaml +56 -0
- package/departments/community/skills/ai-community/SKILL.md +18 -0
- package/departments/community/skills/betting-setup/SKILL.md +18 -0
- package/departments/community/skills/business-model/SKILL.md +53 -0
- package/departments/community/skills/content-calendar/SKILL.md +18 -0
- package/departments/community/skills/events-plan/SKILL.md +18 -0
- package/departments/community/skills/gamification-design/SKILL.md +18 -0
- package/departments/community/skills/growth-plan/SKILL.md +18 -0
- package/departments/community/skills/metrics-track/SKILL.md +18 -0
- package/departments/community/skills/moderation/SKILL.md +18 -0
- package/departments/community/skills/monetize-plan/SKILL.md +18 -0
- package/departments/community/skills/niche-setup/SKILL.md +18 -0
- package/departments/community/skills/onboarding-flow/SKILL.md +18 -0
- package/departments/community/skills/platform-select/SKILL.md +18 -0
- package/departments/community/skills/retention-system/SKILL.md +48 -0
- package/departments/community/squad.yaml +32 -0
- package/departments/community/workflows/setup.yaml +62 -0
- package/departments/content/SKILL.md +65 -0
- package/departments/content/agents/content-strategist.yaml +74 -0
- package/departments/content/agents/repurpose-distributor.yaml +57 -0
- package/departments/content/agents/scriptwriter.yaml +56 -0
- package/departments/content/agents/viral-engineer.yaml +56 -0
- package/departments/content/skills/ai-workflow/SKILL.md +18 -0
- package/departments/content/skills/analytics/SKILL.md +18 -0
- package/departments/content/skills/calendar/SKILL.md +18 -0
- package/departments/content/skills/content-system/SKILL.md +75 -0
- package/departments/content/skills/hook-write/SKILL.md +43 -0
- package/departments/content/skills/monetization-plan/SKILL.md +18 -0
- package/departments/content/skills/newsletter-write/SKILL.md +18 -0
- package/departments/content/skills/platform-optimize/SKILL.md +18 -0
- package/departments/content/skills/repurpose-plan/SKILL.md +18 -0
- package/departments/content/skills/script-structure/SKILL.md +18 -0
- package/departments/content/skills/short-form/SKILL.md +18 -0
- package/departments/content/skills/thumbnail-package/SKILL.md +18 -0
- package/departments/content/skills/viral-design/SKILL.md +45 -0
- package/departments/content/skills/youtube-strategy/SKILL.md +18 -0
- package/departments/content/squad.yaml +39 -0
- package/departments/content/workflows/viral.yaml +99 -0
- package/departments/dev/SKILL.md +135 -0
- package/departments/dev/agents/analyst.md +184 -0
- package/departments/dev/agents/architect.md +184 -0
- package/departments/dev/agents/architect.yaml +74 -0
- package/departments/dev/agents/backend-dev.yaml +70 -0
- package/departments/dev/agents/cto.md +140 -0
- package/departments/dev/agents/cto.yaml +77 -0
- package/departments/dev/agents/dba.yaml +72 -0
- package/departments/dev/agents/devops-eng.yaml +72 -0
- package/departments/dev/agents/devops.md +204 -0
- package/departments/dev/agents/frontend-dev.md +213 -0
- package/departments/dev/agents/frontend-dev.yaml +71 -0
- package/departments/dev/agents/qa-eng.yaml +72 -0
- package/departments/dev/agents/qa.md +231 -0
- package/departments/dev/agents/security-eng.yaml +72 -0
- package/departments/dev/agents/security.md +174 -0
- package/departments/dev/agents/senior-dev.md +177 -0
- package/departments/dev/agents/tech-lead.md +188 -0
- package/departments/dev/agents/tech-lead.yaml +72 -0
- package/departments/dev/skills/adversarial-review/SKILL.md +117 -0
- package/departments/dev/skills/agent-design/SKILL.md +127 -0
- package/departments/dev/skills/agent-workflow/SKILL.md +116 -0
- package/departments/dev/skills/ai-assisted-dev/SKILL.md +18 -0
- package/departments/dev/skills/ai-security/SKILL.md +112 -0
- package/departments/dev/skills/api-design/SKILL.md +59 -0
- package/departments/dev/skills/architecture-design/SKILL.md +89 -0
- package/departments/dev/skills/changelog/SKILL.md +110 -0
- package/departments/dev/skills/ci-cd-pipeline/SKILL.md +130 -0
- package/departments/dev/skills/clean-code-review/SKILL.md +65 -0
- package/departments/dev/skills/code-review/SKILL.md +18 -0
- package/departments/dev/skills/codebase-onboard/SKILL.md +109 -0
- package/departments/dev/skills/db-design/SKILL.md +18 -0
- package/departments/dev/skills/db-schema/SKILL.md +130 -0
- package/departments/dev/skills/ddd-model/SKILL.md +18 -0
- package/departments/dev/skills/dependency-audit/SKILL.md +118 -0
- package/departments/dev/skills/deploy/SKILL.md +18 -0
- package/departments/dev/skills/devops-pipeline/SKILL.md +18 -0
- package/departments/dev/skills/docs/SKILL.md +18 -0
- package/departments/dev/skills/env-secrets/SKILL.md +89 -0
- package/departments/dev/skills/incident/SKILL.md +125 -0
- package/departments/dev/skills/mcp/SKILL.md +106 -0
- package/departments/dev/skills/mcp-builder/SKILL.md +121 -0
- package/departments/dev/skills/observability/SKILL.md +119 -0
- package/departments/dev/skills/onboard/SKILL.md +389 -0
- package/departments/dev/skills/onboard/scripts/detect-stack.py +472 -0
- package/departments/dev/skills/performance-audit/SKILL.md +49 -0
- package/departments/dev/skills/performance-profiler/SKILL.md +128 -0
- package/departments/dev/skills/rag-architect/SKILL.md +125 -0
- package/departments/dev/skills/red-team/SKILL.md +112 -0
- package/departments/dev/skills/refactor-plan/SKILL.md +18 -0
- package/departments/dev/skills/release/SKILL.md +130 -0
- package/departments/dev/skills/research/SKILL.md +18 -0
- package/departments/dev/skills/runbook/SKILL.md +103 -0
- package/departments/dev/skills/scaffold/SKILL.md +249 -0
- package/departments/dev/skills/security-audit/SKILL.md +68 -0
- package/departments/dev/skills/skill-audit/SKILL.md +96 -0
- package/departments/dev/skills/spec/SKILL.md +218 -0
- package/departments/dev/skills/stack-check/SKILL.md +18 -0
- package/departments/dev/skills/tdd-cycle/SKILL.md +56 -0
- package/departments/dev/skills/tech-debt/SKILL.md +100 -0
- package/departments/dev/squad.yaml +62 -0
- package/departments/dev/workflows/debug.yaml +63 -0
- package/departments/dev/workflows/feature.yaml +129 -0
- package/departments/dev/workflows/refactor.yaml +64 -0
- package/departments/ecom/SKILL.md +39 -0
- package/departments/ecom/agents/commerce-engineer.yaml +58 -0
- package/departments/ecom/agents/cro-specialist.yaml +56 -0
- package/departments/ecom/agents/ecom-director.yaml +73 -0
- package/departments/ecom/agents/retention-manager.yaml +59 -0
- package/departments/ecom/skills/analytics/SKILL.md +18 -0
- package/departments/ecom/skills/cart-recovery/SKILL.md +18 -0
- package/departments/ecom/skills/cro-optimize/SKILL.md +58 -0
- package/departments/ecom/skills/customer-journey/SKILL.md +18 -0
- package/departments/ecom/skills/fulfillment-plan/SKILL.md +18 -0
- package/departments/ecom/skills/marketplace-manage/SKILL.md +18 -0
- package/departments/ecom/skills/pricing-strategy/SKILL.md +18 -0
- package/departments/ecom/skills/product-launch/SKILL.md +18 -0
- package/departments/ecom/skills/rfm-segment/SKILL.md +44 -0
- package/departments/ecom/skills/social-commerce/SKILL.md +18 -0
- package/departments/ecom/skills/store-audit/SKILL.md +18 -0
- package/departments/ecom/skills/subscription-model/SKILL.md +18 -0
- package/departments/ecom/squad.yaml +39 -0
- package/departments/ecom/workflows/product-page.yaml +62 -0
- package/departments/ecommerce/SKILL.md +363 -0
- package/departments/ecommerce/agents/ecommerce-manager.md +91 -0
- package/departments/finance/SKILL.md +37 -0
- package/departments/finance/agents/cfo.md +85 -0
- package/departments/finance/agents/cfo.yaml +77 -0
- package/departments/finance/agents/financial-analyst.yaml +57 -0
- package/departments/finance/agents/investment-strategist.yaml +58 -0
- package/departments/finance/skills/budget-plan/SKILL.md +18 -0
- package/departments/finance/skills/cashflow-forecast/SKILL.md +18 -0
- package/departments/finance/skills/ciso-advisor/SKILL.md +113 -0
- package/departments/finance/skills/financial-model/SKILL.md +70 -0
- package/departments/finance/skills/pitch-deck/SKILL.md +18 -0
- package/departments/finance/skills/scenario-analysis/SKILL.md +18 -0
- package/departments/finance/skills/unit-economics/SKILL.md +44 -0
- package/departments/finance/skills/valuation-model/SKILL.md +18 -0
- package/departments/finance/squad.yaml +37 -0
- package/departments/finance/workflows/cashflow.yaml +47 -0
- package/departments/finance/workflows/model.yaml +83 -0
- package/departments/kb/SKILL.md +38 -0
- package/departments/kb/agents/knowledge-curator.yaml +60 -0
- package/departments/kb/agents/knowledge-director.yaml +72 -0
- package/departments/kb/agents/research-analyst.yaml +58 -0
- package/departments/kb/skills/ai-research/SKILL.md +18 -0
- package/departments/kb/skills/competitive-intel/SKILL.md +18 -0
- package/departments/kb/skills/knowledge-review/SKILL.md +18 -0
- package/departments/kb/skills/learn-content/SKILL.md +18 -0
- package/departments/kb/skills/moc-create/SKILL.md +18 -0
- package/departments/kb/skills/persona-build/SKILL.md +18 -0
- package/departments/kb/skills/research-plan/SKILL.md +51 -0
- package/departments/kb/skills/search-kb/SKILL.md +18 -0
- package/departments/kb/skills/source-evaluate/SKILL.md +18 -0
- package/departments/kb/skills/taxonomy-manage/SKILL.md +18 -0
- package/departments/kb/skills/write-as-persona/SKILL.md +18 -0
- package/departments/kb/skills/zettelkasten-process/SKILL.md +56 -0
- package/departments/kb/squad.yaml +34 -0
- package/departments/kb/workflows/learn.yaml +63 -0
- package/departments/knowledge/SKILL.md +474 -0
- package/departments/knowledge/agents/knowledge-curator.md +89 -0
- package/departments/knowledge/scripts/kb-check-capabilities.sh +143 -0
- package/departments/knowledge/scripts/kb-cleanup.sh +135 -0
- package/departments/knowledge/scripts/kb-queue.sh +156 -0
- package/departments/knowledge/scripts/kb-status.sh +195 -0
- package/departments/knowledge/scripts/kb-worker.sh +217 -0
- package/departments/landing/SKILL.md +65 -0
- package/departments/landing/agents/affiliate-manager.yaml +57 -0
- package/departments/landing/agents/conversion-strategist.yaml +74 -0
- package/departments/landing/agents/cro-specialist.yaml +58 -0
- package/departments/landing/agents/sales-copywriter.yaml +61 -0
- package/departments/landing/skills/ab-test/SKILL.md +18 -0
- package/departments/landing/skills/affiliate-bridge/SKILL.md +18 -0
- package/departments/landing/skills/awareness-diagnose/SKILL.md +18 -0
- package/departments/landing/skills/copy-framework/SKILL.md +55 -0
- package/departments/landing/skills/email-sequence/SKILL.md +18 -0
- package/departments/landing/skills/funnel-design/SKILL.md +49 -0
- package/departments/landing/skills/funnel-metrics/SKILL.md +18 -0
- package/departments/landing/skills/headline-write/SKILL.md +18 -0
- package/departments/landing/skills/landing-gen/SKILL.md +124 -0
- package/departments/landing/skills/launch-sequence/SKILL.md +18 -0
- package/departments/landing/skills/offer-create/SKILL.md +62 -0
- package/departments/landing/skills/optimize-page/SKILL.md +18 -0
- package/departments/landing/skills/page-architect/SKILL.md +18 -0
- package/departments/landing/skills/persuasion-apply/SKILL.md +18 -0
- package/departments/landing/skills/webinar-funnel/SKILL.md +18 -0
- package/departments/landing/squad.yaml +39 -0
- package/departments/landing/workflows/launch.yaml +72 -0
- package/departments/landing/workflows/offer.yaml +99 -0
- package/departments/leadership/SKILL.md +35 -0
- package/departments/leadership/agents/culture-coach.yaml +59 -0
- package/departments/leadership/agents/hr-specialist.yaml +57 -0
- package/departments/leadership/agents/leadership-director.yaml +72 -0
- package/departments/leadership/skills/change-manage/SKILL.md +18 -0
- package/departments/leadership/skills/conflict-resolve/SKILL.md +18 -0
- package/departments/leadership/skills/culture-audit/SKILL.md +18 -0
- package/departments/leadership/skills/delegation-matrix/SKILL.md +18 -0
- package/departments/leadership/skills/disc-assess/SKILL.md +18 -0
- package/departments/leadership/skills/feedback-give/SKILL.md +18 -0
- package/departments/leadership/skills/hiring-plan/SKILL.md +18 -0
- package/departments/leadership/skills/okr-define/SKILL.md +69 -0
- package/departments/leadership/skills/performance-review/SKILL.md +18 -0
- package/departments/leadership/skills/team-health/SKILL.md +56 -0
- package/departments/leadership/squad.yaml +35 -0
- package/departments/leadership/workflows/team-build.yaml +55 -0
- package/departments/marketing/SKILL.md +61 -0
- package/departments/marketing/agents/content-creator.md +85 -0
- package/departments/marketing/agents/content-marketer.yaml +58 -0
- package/departments/marketing/agents/marketing-director.yaml +75 -0
- package/departments/marketing/agents/paid-specialist.yaml +58 -0
- package/departments/marketing/agents/seo-specialist.yaml +57 -0
- package/departments/marketing/skills/ab-test/SKILL.md +18 -0
- package/departments/marketing/skills/analytics-report/SKILL.md +18 -0
- package/departments/marketing/skills/audience-segment/SKILL.md +18 -0
- package/departments/marketing/skills/calendar-plan/SKILL.md +18 -0
- package/departments/marketing/skills/cold-email/SKILL.md +128 -0
- package/departments/marketing/skills/competitor-analysis/SKILL.md +18 -0
- package/departments/marketing/skills/content-audit/SKILL.md +18 -0
- package/departments/marketing/skills/email-sequence/SKILL.md +18 -0
- package/departments/marketing/skills/growth-loop/SKILL.md +50 -0
- package/departments/marketing/skills/marketing-automation/SKILL.md +18 -0
- package/departments/marketing/skills/paid-campaign/SKILL.md +18 -0
- package/departments/marketing/skills/programmatic-seo/SKILL.md +123 -0
- package/departments/marketing/skills/seo-audit/SKILL.md +48 -0
- package/departments/marketing/skills/social-strategy/SKILL.md +18 -0
- package/departments/marketing/squad.yaml +39 -0
- package/departments/marketing/workflows/campaign.yaml +112 -0
- package/departments/marketing/workflows/social.yaml +56 -0
- package/departments/operations/SKILL.md +422 -0
- package/departments/operations/agents/coo.md +88 -0
- package/departments/ops/SKILL.md +37 -0
- package/departments/ops/agents/automation-engineer.yaml +58 -0
- package/departments/ops/agents/ops-lead.yaml +71 -0
- package/departments/ops/skills/bottleneck-find/SKILL.md +49 -0
- package/departments/ops/skills/dashboard-build/SKILL.md +18 -0
- package/departments/ops/skills/gtd-setup/SKILL.md +18 -0
- package/departments/ops/skills/integration-design/SKILL.md +18 -0
- package/departments/ops/skills/lean-audit/SKILL.md +18 -0
- package/departments/ops/skills/metrics-dashboard/SKILL.md +18 -0
- package/departments/ops/skills/n8n-flow/SKILL.md +18 -0
- package/departments/ops/skills/sop-create/SKILL.md +18 -0
- package/departments/ops/skills/workflow-automate/SKILL.md +39 -0
- package/departments/ops/skills/zapier-flow/SKILL.md +18 -0
- package/departments/ops/squad.yaml +35 -0
- package/departments/ops/workflows/lean-audit.yaml +69 -0
- package/departments/org/SKILL.md +34 -0
- package/departments/org/agents/coo.yaml +80 -0
- package/departments/org/agents/org-designer.yaml +56 -0
- package/departments/org/agents/people-ops.yaml +56 -0
- package/departments/org/skills/compensation-plan/SKILL.md +18 -0
- package/departments/org/skills/culture-define/SKILL.md +18 -0
- package/departments/org/skills/decision-framework/SKILL.md +18 -0
- package/departments/org/skills/hiring-plan/SKILL.md +18 -0
- package/departments/org/skills/meeting-optimize/SKILL.md +18 -0
- package/departments/org/skills/onboarding-design/SKILL.md +18 -0
- package/departments/org/skills/org-design/SKILL.md +18 -0
- package/departments/org/skills/remote-setup/SKILL.md +18 -0
- package/departments/org/skills/sop-process/SKILL.md +18 -0
- package/departments/org/skills/team-assess/SKILL.md +18 -0
- package/departments/org/squad.yaml +33 -0
- package/departments/org/workflows/design.yaml +55 -0
- package/departments/pm/SKILL.md +39 -0
- package/departments/pm/agents/pm-director.yaml +75 -0
- package/departments/pm/agents/product-owner.yaml +59 -0
- package/departments/pm/agents/scrum-master.yaml +59 -0
- package/departments/pm/skills/agile-po/SKILL.md +118 -0
- package/departments/pm/skills/backlog-groom/SKILL.md +18 -0
- package/departments/pm/skills/discovery-plan/SKILL.md +48 -0
- package/departments/pm/skills/estimate-forecast/SKILL.md +18 -0
- package/departments/pm/skills/impact-map/SKILL.md +18 -0
- package/departments/pm/skills/kanban-setup/SKILL.md +18 -0
- package/departments/pm/skills/risk-register/SKILL.md +18 -0
- package/departments/pm/skills/roadmap-build/SKILL.md +18 -0
- package/departments/pm/skills/shape-pitch/SKILL.md +55 -0
- package/departments/pm/skills/sprint-plan/SKILL.md +18 -0
- package/departments/pm/skills/stakeholder-map/SKILL.md +18 -0
- package/departments/pm/skills/standup-run/SKILL.md +18 -0
- package/departments/pm/skills/story-write/SKILL.md +18 -0
- package/departments/pm/squad.yaml +37 -0
- package/departments/pm/workflows/retro.yaml +33 -0
- package/departments/quality/SKILL.md +66 -0
- package/departments/quality/agents/copy-director.md +134 -0
- package/departments/quality/agents/copy-director.yaml +73 -0
- package/departments/quality/agents/cqo.md +134 -0
- package/departments/quality/agents/cqo.yaml +76 -0
- package/departments/quality/agents/tech-director.yaml +79 -0
- package/departments/quality/agents/tech-ux-director.md +193 -0
- package/departments/quality/squad.yaml +25 -0
- package/departments/saas/SKILL.md +64 -0
- package/departments/saas/agents/cs-manager.yaml +57 -0
- package/departments/saas/agents/growth-engineer.yaml +57 -0
- package/departments/saas/agents/metrics-analyst.yaml +57 -0
- package/departments/saas/agents/saas-strategist.yaml +74 -0
- package/departments/saas/skills/benchmark-compare/SKILL.md +18 -0
- package/departments/saas/skills/churn-analysis/SKILL.md +18 -0
- package/departments/saas/skills/customer-success/SKILL.md +18 -0
- package/departments/saas/skills/growth-plan/SKILL.md +18 -0
- package/departments/saas/skills/gtm-strategy/SKILL.md +18 -0
- package/departments/saas/skills/launch-execute/SKILL.md +18 -0
- package/departments/saas/skills/metrics-dashboard/SKILL.md +18 -0
- package/departments/saas/skills/micro-saas-stack/SKILL.md +18 -0
- package/departments/saas/skills/mvp-build/SKILL.md +18 -0
- package/departments/saas/skills/niche-evaluate/SKILL.md +18 -0
- package/departments/saas/skills/onboarding-optimize/SKILL.md +18 -0
- package/departments/saas/skills/plg-setup/SKILL.md +53 -0
- package/departments/saas/skills/pricing-strategy/SKILL.md +48 -0
- package/departments/saas/skills/saas-scaffold/SKILL.md +127 -0
- package/departments/saas/skills/validate-idea/SKILL.md +55 -0
- package/departments/saas/squad.yaml +37 -0
- package/departments/saas/workflows/metrics.yaml +58 -0
- package/departments/saas/workflows/validate.yaml +103 -0
- package/departments/sales/SKILL.md +35 -0
- package/departments/sales/agents/sales-closer.yaml +58 -0
- package/departments/sales/agents/sales-director.yaml +72 -0
- package/departments/sales/agents/sales-ops.yaml +55 -0
- package/departments/sales/skills/challenger-sell/SKILL.md +18 -0
- package/departments/sales/skills/deal-qualify/SKILL.md +18 -0
- package/departments/sales/skills/discovery-call/SKILL.md +18 -0
- package/departments/sales/skills/forecast-revenue/SKILL.md +18 -0
- package/departments/sales/skills/negotiate-plan/SKILL.md +18 -0
- package/departments/sales/skills/objection-handle/SKILL.md +18 -0
- package/departments/sales/skills/pipeline-manage/SKILL.md +18 -0
- package/departments/sales/skills/pricing-negotiate/SKILL.md +18 -0
- package/departments/sales/skills/proposal-write/SKILL.md +54 -0
- package/departments/sales/skills/spin-sell/SKILL.md +50 -0
- package/departments/sales/squad.yaml +35 -0
- package/departments/sales/workflows/pipeline.yaml +49 -0
- package/departments/strategy/SKILL.md +37 -0
- package/departments/strategy/agents/business-model-designer.yaml +58 -0
- package/departments/strategy/agents/market-analyst.yaml +58 -0
- package/departments/strategy/agents/strategist.md +79 -0
- package/departments/strategy/agents/strategy-director.yaml +75 -0
- package/departments/strategy/skills/blue-ocean/SKILL.md +56 -0
- package/departments/strategy/skills/bmc/SKILL.md +18 -0
- package/departments/strategy/skills/board-advisor/SKILL.md +121 -0
- package/departments/strategy/skills/cto-advisor/SKILL.md +113 -0
- package/departments/strategy/skills/five-forces/SKILL.md +74 -0
- package/departments/strategy/skills/growth-strategy/SKILL.md +18 -0
- package/departments/strategy/skills/moat-analysis/SKILL.md +18 -0
- package/departments/strategy/skills/position/SKILL.md +18 -0
- package/departments/strategy/skills/scenario-plan/SKILL.md +18 -0
- package/departments/strategy/squad.yaml +37 -0
- package/departments/strategy/workflows/analysis.yaml +90 -0
- package/departments/strategy/workflows/swot.yaml +47 -0
- package/installer/adapters/claude-code.js +73 -0
- package/installer/adapters/codex-cli.js +34 -0
- package/installer/adapters/cursor.js +34 -0
- package/installer/adapters/gemini-cli.js +37 -0
- package/installer/cli.js +91 -0
- package/installer/detect-runtime.js +122 -0
- package/installer/doctor.js +105 -0
- package/installer/index.js +199 -0
- package/installer/uninstall.js +46 -0
- package/installer/update.js +39 -0
- package/knowledge/agents-registry-v2.json +2702 -0
- package/knowledge/commands-registry-v2.json +3827 -0
- package/package.json +58 -0
- package/pyproject.toml +64 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""Task manager — queue, track, and manage background tasks."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
from core.tasks.schema import Task, TaskStatus, TaskType
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TaskManager:
|
|
12
|
+
"""Manages background task lifecycle.
|
|
13
|
+
|
|
14
|
+
Tasks are stored in memory and optionally persisted to a JSON file
|
|
15
|
+
for cross-session recovery.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, storage_path: str | Path = "") -> None:
|
|
19
|
+
self._tasks: dict[str, Task] = {}
|
|
20
|
+
self._counter: int = 0
|
|
21
|
+
self._storage_path = Path(storage_path) if storage_path else None
|
|
22
|
+
if self._storage_path and self._storage_path.exists():
|
|
23
|
+
self._load()
|
|
24
|
+
|
|
25
|
+
def create(
|
|
26
|
+
self,
|
|
27
|
+
title: str,
|
|
28
|
+
task_type: TaskType = TaskType.CUSTOM,
|
|
29
|
+
description: str = "",
|
|
30
|
+
department: str = "",
|
|
31
|
+
agent_id: str = "",
|
|
32
|
+
input_data: dict | None = None,
|
|
33
|
+
) -> Task:
|
|
34
|
+
"""Create and queue a new task."""
|
|
35
|
+
self._counter += 1
|
|
36
|
+
task_id = f"task-{self._counter:04d}"
|
|
37
|
+
|
|
38
|
+
task = Task(
|
|
39
|
+
id=task_id,
|
|
40
|
+
type=task_type,
|
|
41
|
+
title=title,
|
|
42
|
+
description=description,
|
|
43
|
+
status=TaskStatus.QUEUED,
|
|
44
|
+
department=department,
|
|
45
|
+
agent_id=agent_id,
|
|
46
|
+
input_data=input_data or {},
|
|
47
|
+
created_at=datetime.now().isoformat(),
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
self._tasks[task_id] = task
|
|
51
|
+
self._save()
|
|
52
|
+
return task
|
|
53
|
+
|
|
54
|
+
def get(self, task_id: str) -> Optional[Task]:
|
|
55
|
+
return self._tasks.get(task_id)
|
|
56
|
+
|
|
57
|
+
def start(self, task_id: str) -> bool:
|
|
58
|
+
task = self._tasks.get(task_id)
|
|
59
|
+
if task is None or task.is_terminal:
|
|
60
|
+
return False
|
|
61
|
+
task.start()
|
|
62
|
+
self._save()
|
|
63
|
+
return True
|
|
64
|
+
|
|
65
|
+
def complete(self, task_id: str, output: dict | None = None, path: str = "") -> bool:
|
|
66
|
+
task = self._tasks.get(task_id)
|
|
67
|
+
if task is None:
|
|
68
|
+
return False
|
|
69
|
+
task.complete(output, path)
|
|
70
|
+
self._save()
|
|
71
|
+
return True
|
|
72
|
+
|
|
73
|
+
def fail(self, task_id: str, error: str) -> bool:
|
|
74
|
+
task = self._tasks.get(task_id)
|
|
75
|
+
if task is None:
|
|
76
|
+
return False
|
|
77
|
+
task.fail(error)
|
|
78
|
+
self._save()
|
|
79
|
+
return True
|
|
80
|
+
|
|
81
|
+
def cancel(self, task_id: str) -> bool:
|
|
82
|
+
task = self._tasks.get(task_id)
|
|
83
|
+
if task is None or task.is_terminal:
|
|
84
|
+
return False
|
|
85
|
+
task.cancel()
|
|
86
|
+
self._save()
|
|
87
|
+
return True
|
|
88
|
+
|
|
89
|
+
def update_progress(self, task_id: str, percent: int, message: str = "") -> bool:
|
|
90
|
+
task = self._tasks.get(task_id)
|
|
91
|
+
if task is None:
|
|
92
|
+
return False
|
|
93
|
+
task.update_progress(percent, message)
|
|
94
|
+
self._save()
|
|
95
|
+
return True
|
|
96
|
+
|
|
97
|
+
def list_all(self, status: Optional[TaskStatus] = None) -> list[Task]:
|
|
98
|
+
if status:
|
|
99
|
+
return [t for t in self._tasks.values() if t.status == status]
|
|
100
|
+
return list(self._tasks.values())
|
|
101
|
+
|
|
102
|
+
def list_active(self) -> list[Task]:
|
|
103
|
+
return [t for t in self._tasks.values() if t.is_active]
|
|
104
|
+
|
|
105
|
+
def list_queued(self) -> list[Task]:
|
|
106
|
+
return self.list_all(TaskStatus.QUEUED)
|
|
107
|
+
|
|
108
|
+
def cleanup_completed(self, keep_last: int = 50) -> int:
|
|
109
|
+
"""Remove old completed tasks, keeping the most recent."""
|
|
110
|
+
completed = [t for t in self._tasks.values() if t.is_terminal]
|
|
111
|
+
completed.sort(key=lambda t: t.completed_at or t.created_at, reverse=True)
|
|
112
|
+
to_remove = completed[keep_last:]
|
|
113
|
+
for task in to_remove:
|
|
114
|
+
del self._tasks[task.id]
|
|
115
|
+
if to_remove:
|
|
116
|
+
self._save()
|
|
117
|
+
return len(to_remove)
|
|
118
|
+
|
|
119
|
+
def summary(self) -> dict:
|
|
120
|
+
by_status: dict[str, int] = {}
|
|
121
|
+
for task in self._tasks.values():
|
|
122
|
+
by_status[task.status.value] = by_status.get(task.status.value, 0) + 1
|
|
123
|
+
return {
|
|
124
|
+
"total": len(self._tasks),
|
|
125
|
+
"by_status": by_status,
|
|
126
|
+
"active": len(self.list_active()),
|
|
127
|
+
"queued": len(self.list_queued()),
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
def _save(self) -> None:
|
|
131
|
+
if self._storage_path is None:
|
|
132
|
+
return
|
|
133
|
+
self._storage_path.parent.mkdir(parents=True, exist_ok=True)
|
|
134
|
+
data = {
|
|
135
|
+
"counter": self._counter,
|
|
136
|
+
"tasks": {tid: t.model_dump(mode="json") for tid, t in self._tasks.items()},
|
|
137
|
+
}
|
|
138
|
+
with open(self._storage_path, "w") as f:
|
|
139
|
+
json.dump(data, f, indent=2)
|
|
140
|
+
|
|
141
|
+
def _load(self) -> None:
|
|
142
|
+
if self._storage_path is None or not self._storage_path.exists():
|
|
143
|
+
return
|
|
144
|
+
content = self._storage_path.read_text().strip()
|
|
145
|
+
if not content:
|
|
146
|
+
return
|
|
147
|
+
data = json.loads(content)
|
|
148
|
+
self._counter = data.get("counter", 0)
|
|
149
|
+
for tid, tdata in data.get("tasks", {}).items():
|
|
150
|
+
self._tasks[tid] = Task.model_validate(tdata)
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Task schema for background operations.
|
|
2
|
+
|
|
3
|
+
Tasks represent async work: KB downloads, transcriptions, long-running
|
|
4
|
+
analysis, AI generation, etc. Each task has a lifecycle and can be
|
|
5
|
+
queried for status.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from enum import Enum
|
|
10
|
+
from typing import Optional, Any
|
|
11
|
+
from pydantic import BaseModel, Field
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TaskStatus(str, Enum):
|
|
15
|
+
QUEUED = "queued"
|
|
16
|
+
DOWNLOADING = "downloading"
|
|
17
|
+
PROCESSING = "processing"
|
|
18
|
+
READY = "ready" # Needs human/AI interaction to continue
|
|
19
|
+
ANALYZING = "analyzing"
|
|
20
|
+
COMPLETED = "completed"
|
|
21
|
+
FAILED = "failed"
|
|
22
|
+
CANCELLED = "cancelled"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class TaskType(str, Enum):
|
|
26
|
+
KB_DOWNLOAD = "kb_download" # Download media (YouTube, etc.)
|
|
27
|
+
KB_TRANSCRIBE = "kb_transcribe" # Transcribe audio/video
|
|
28
|
+
KB_ANALYZE = "kb_analyze" # AI analysis of content
|
|
29
|
+
RESEARCH = "research" # Background research
|
|
30
|
+
GENERATION = "generation" # AI content/image generation
|
|
31
|
+
EXPORT = "export" # Export to external system
|
|
32
|
+
CUSTOM = "custom"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class Task(BaseModel):
|
|
36
|
+
"""A background task with lifecycle tracking."""
|
|
37
|
+
id: str
|
|
38
|
+
type: TaskType = TaskType.CUSTOM
|
|
39
|
+
title: str
|
|
40
|
+
description: str = ""
|
|
41
|
+
status: TaskStatus = TaskStatus.QUEUED
|
|
42
|
+
department: str = ""
|
|
43
|
+
agent_id: str = ""
|
|
44
|
+
|
|
45
|
+
# Input/output
|
|
46
|
+
input_data: dict[str, Any] = Field(default_factory=dict)
|
|
47
|
+
output_data: dict[str, Any] = Field(default_factory=dict)
|
|
48
|
+
output_path: str = "" # File path for output
|
|
49
|
+
|
|
50
|
+
# Progress
|
|
51
|
+
progress_percent: int = 0 # 0-100
|
|
52
|
+
progress_message: str = ""
|
|
53
|
+
|
|
54
|
+
# Timing
|
|
55
|
+
created_at: str = ""
|
|
56
|
+
started_at: str = ""
|
|
57
|
+
completed_at: str = ""
|
|
58
|
+
|
|
59
|
+
# Error
|
|
60
|
+
error: str = ""
|
|
61
|
+
retry_count: int = 0
|
|
62
|
+
max_retries: int = 3
|
|
63
|
+
|
|
64
|
+
def start(self) -> None:
|
|
65
|
+
self.status = TaskStatus.PROCESSING
|
|
66
|
+
self.started_at = datetime.now().isoformat()
|
|
67
|
+
|
|
68
|
+
def complete(self, output: dict | None = None, path: str = "") -> None:
|
|
69
|
+
self.status = TaskStatus.COMPLETED
|
|
70
|
+
self.completed_at = datetime.now().isoformat()
|
|
71
|
+
self.progress_percent = 100
|
|
72
|
+
if output:
|
|
73
|
+
self.output_data = output
|
|
74
|
+
if path:
|
|
75
|
+
self.output_path = path
|
|
76
|
+
|
|
77
|
+
def fail(self, error: str) -> None:
|
|
78
|
+
self.error = error
|
|
79
|
+
if self.retry_count < self.max_retries:
|
|
80
|
+
self.retry_count += 1
|
|
81
|
+
self.status = TaskStatus.QUEUED
|
|
82
|
+
self.progress_message = f"Retry {self.retry_count}/{self.max_retries}"
|
|
83
|
+
else:
|
|
84
|
+
self.status = TaskStatus.FAILED
|
|
85
|
+
|
|
86
|
+
def cancel(self) -> None:
|
|
87
|
+
self.status = TaskStatus.CANCELLED
|
|
88
|
+
|
|
89
|
+
def update_progress(self, percent: int, message: str = "") -> None:
|
|
90
|
+
self.progress_percent = min(percent, 100)
|
|
91
|
+
if message:
|
|
92
|
+
self.progress_message = message
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def is_terminal(self) -> bool:
|
|
96
|
+
return self.status in (TaskStatus.COMPLETED, TaskStatus.FAILED, TaskStatus.CANCELLED)
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def is_active(self) -> bool:
|
|
100
|
+
return self.status in (TaskStatus.DOWNLOADING, TaskStatus.PROCESSING, TaskStatus.ANALYZING)
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def duration_seconds(self) -> float | None:
|
|
104
|
+
if not self.started_at:
|
|
105
|
+
return None
|
|
106
|
+
start = datetime.fromisoformat(self.started_at)
|
|
107
|
+
end = datetime.fromisoformat(self.completed_at) if self.completed_at else datetime.now()
|
|
108
|
+
return (end - start).total_seconds()
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""YAML-based workflow engine for ArkaOS v2.
|
|
2
|
+
|
|
3
|
+
Declarative workflows with phases, conditions, gates, and parallelization.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from core.workflow.schema import Workflow, Phase, Gate, PhaseStatus
|
|
7
|
+
from core.workflow.engine import WorkflowEngine
|
|
8
|
+
from core.workflow.loader import load_workflow
|
|
9
|
+
|
|
10
|
+
__all__ = ["Workflow", "Phase", "Gate", "PhaseStatus", "WorkflowEngine", "load_workflow"]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"""Workflow execution engine.
|
|
2
|
+
|
|
3
|
+
Executes workflows phase by phase, respecting gates, conditions,
|
|
4
|
+
and agent assignments. Enforces the Constitution's sequential validation
|
|
5
|
+
and full visibility rules.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
|
+
from typing import Optional, Callable, Any
|
|
10
|
+
|
|
11
|
+
from core.workflow.schema import (
|
|
12
|
+
Workflow, Phase, PhaseStatus, GateType, Gate,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class PhaseResult:
|
|
18
|
+
"""Result of executing a single phase."""
|
|
19
|
+
phase_id: str
|
|
20
|
+
status: PhaseStatus
|
|
21
|
+
output: str = ""
|
|
22
|
+
agent_outputs: dict[str, str] = field(default_factory=dict)
|
|
23
|
+
duration_ms: int = 0
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class GateResult:
|
|
28
|
+
"""Result of evaluating a gate."""
|
|
29
|
+
passed: bool
|
|
30
|
+
gate_type: GateType
|
|
31
|
+
message: str = ""
|
|
32
|
+
verdict: str = ""
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class WorkflowEngine:
|
|
36
|
+
"""Executes YAML-defined workflows with phase gates and visibility.
|
|
37
|
+
|
|
38
|
+
The engine enforces:
|
|
39
|
+
1. Sequential validation — Phase N+1 only starts after N completes
|
|
40
|
+
2. Full visibility — Every phase announces what's starting and what resulted
|
|
41
|
+
3. Quality Gate — Mandatory review before delivery
|
|
42
|
+
4. Gate evaluation — User approval, quality checks, or conditions
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
on_phase_start: Optional[Callable[[Phase], None]] = None,
|
|
48
|
+
on_phase_complete: Optional[Callable[[Phase, PhaseResult], None]] = None,
|
|
49
|
+
on_gate_check: Optional[Callable[[Gate], GateResult]] = None,
|
|
50
|
+
on_visibility: Optional[Callable[[str], None]] = None,
|
|
51
|
+
):
|
|
52
|
+
"""Initialize the workflow engine.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
on_phase_start: Called when a phase begins execution.
|
|
56
|
+
on_phase_complete: Called when a phase finishes.
|
|
57
|
+
on_gate_check: Called to evaluate a gate. Must return GateResult.
|
|
58
|
+
on_visibility: Called to announce status to the user.
|
|
59
|
+
"""
|
|
60
|
+
self._on_phase_start = on_phase_start
|
|
61
|
+
self._on_phase_complete = on_phase_complete
|
|
62
|
+
self._on_gate_check = on_gate_check
|
|
63
|
+
self._on_visibility = on_visibility
|
|
64
|
+
self._history: list[PhaseResult] = []
|
|
65
|
+
|
|
66
|
+
def announce(self, message: str) -> None:
|
|
67
|
+
"""Announce a status message (full visibility rule)."""
|
|
68
|
+
if self._on_visibility:
|
|
69
|
+
self._on_visibility(message)
|
|
70
|
+
|
|
71
|
+
def execute(self, workflow: Workflow) -> list[PhaseResult]:
|
|
72
|
+
"""Execute a workflow from start to finish.
|
|
73
|
+
|
|
74
|
+
Phases run sequentially. Each phase must complete and pass
|
|
75
|
+
its gate before the next phase starts.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
workflow: The workflow definition to execute.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
List of PhaseResults for each executed phase.
|
|
82
|
+
"""
|
|
83
|
+
workflow.status = PhaseStatus.IN_PROGRESS
|
|
84
|
+
results: list[PhaseResult] = []
|
|
85
|
+
|
|
86
|
+
self.announce(
|
|
87
|
+
f"Starting workflow: {workflow.name} "
|
|
88
|
+
f"({len(workflow.phases)} phases, tier: {workflow.tier.value})"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
for i, phase in enumerate(workflow.phases):
|
|
92
|
+
# Check skip condition
|
|
93
|
+
if phase.skip_if and self._evaluate_condition(phase.skip_if):
|
|
94
|
+
phase.status = PhaseStatus.SKIPPED
|
|
95
|
+
self.announce(f"Phase {i}: {phase.name} — SKIPPED (condition met)")
|
|
96
|
+
results.append(PhaseResult(
|
|
97
|
+
phase_id=phase.id,
|
|
98
|
+
status=PhaseStatus.SKIPPED,
|
|
99
|
+
output="Skipped: condition evaluated to true",
|
|
100
|
+
))
|
|
101
|
+
continue
|
|
102
|
+
|
|
103
|
+
# Check dependencies
|
|
104
|
+
if phase.depends_on:
|
|
105
|
+
unmet = [
|
|
106
|
+
dep for dep in phase.depends_on
|
|
107
|
+
if not self._is_phase_complete(workflow, dep)
|
|
108
|
+
]
|
|
109
|
+
if unmet:
|
|
110
|
+
phase.status = PhaseStatus.BLOCKED
|
|
111
|
+
self.announce(
|
|
112
|
+
f"Phase {i}: {phase.name} — BLOCKED "
|
|
113
|
+
f"(waiting for: {', '.join(unmet)})"
|
|
114
|
+
)
|
|
115
|
+
results.append(PhaseResult(
|
|
116
|
+
phase_id=phase.id,
|
|
117
|
+
status=PhaseStatus.BLOCKED,
|
|
118
|
+
output=f"Blocked by: {', '.join(unmet)}",
|
|
119
|
+
))
|
|
120
|
+
continue
|
|
121
|
+
|
|
122
|
+
# Execute phase
|
|
123
|
+
self.announce(
|
|
124
|
+
f"Phase {i}: {phase.name} — STARTING "
|
|
125
|
+
f"(agents: {', '.join(a.agent_id for a in phase.agents)})"
|
|
126
|
+
)
|
|
127
|
+
phase.status = PhaseStatus.IN_PROGRESS
|
|
128
|
+
|
|
129
|
+
if self._on_phase_start:
|
|
130
|
+
self._on_phase_start(phase)
|
|
131
|
+
|
|
132
|
+
result = self._execute_phase(phase)
|
|
133
|
+
results.append(result)
|
|
134
|
+
|
|
135
|
+
if result.status == PhaseStatus.FAILED:
|
|
136
|
+
phase.status = PhaseStatus.FAILED
|
|
137
|
+
workflow.status = PhaseStatus.FAILED
|
|
138
|
+
self.announce(f"Phase {i}: {phase.name} — FAILED: {result.output}")
|
|
139
|
+
break
|
|
140
|
+
|
|
141
|
+
phase.status = PhaseStatus.COMPLETED
|
|
142
|
+
phase.result = result.output
|
|
143
|
+
|
|
144
|
+
if self._on_phase_complete:
|
|
145
|
+
self._on_phase_complete(phase, result)
|
|
146
|
+
|
|
147
|
+
self.announce(f"Phase {i}: {phase.name} — COMPLETED")
|
|
148
|
+
|
|
149
|
+
# Evaluate gate
|
|
150
|
+
gate_result = self._evaluate_gate(phase.gate)
|
|
151
|
+
if not gate_result.passed:
|
|
152
|
+
self.announce(
|
|
153
|
+
f"Gate after Phase {i} — REJECTED: {gate_result.message}"
|
|
154
|
+
)
|
|
155
|
+
# Loop back: reset phase to pending for retry
|
|
156
|
+
phase.status = PhaseStatus.PENDING
|
|
157
|
+
results.append(PhaseResult(
|
|
158
|
+
phase_id=f"{phase.id}_gate",
|
|
159
|
+
status=PhaseStatus.FAILED,
|
|
160
|
+
output=f"Gate rejected: {gate_result.message}",
|
|
161
|
+
))
|
|
162
|
+
workflow.status = PhaseStatus.FAILED
|
|
163
|
+
break
|
|
164
|
+
|
|
165
|
+
if workflow.all_phases_complete():
|
|
166
|
+
workflow.status = PhaseStatus.COMPLETED
|
|
167
|
+
self.announce(f"Workflow {workflow.name} — COMPLETED")
|
|
168
|
+
|
|
169
|
+
self._history.extend(results)
|
|
170
|
+
return results
|
|
171
|
+
|
|
172
|
+
def _execute_phase(self, phase: Phase) -> PhaseResult:
|
|
173
|
+
"""Execute a single phase.
|
|
174
|
+
|
|
175
|
+
In the real implementation, this dispatches to agents via
|
|
176
|
+
the runtime adapter. Here we return a placeholder result
|
|
177
|
+
that the calling code fills in.
|
|
178
|
+
"""
|
|
179
|
+
agent_ids = [a.agent_id for a in phase.agents]
|
|
180
|
+
return PhaseResult(
|
|
181
|
+
phase_id=phase.id,
|
|
182
|
+
status=PhaseStatus.COMPLETED,
|
|
183
|
+
output=f"Phase {phase.name} executed by {', '.join(agent_ids)}",
|
|
184
|
+
agent_outputs={a.agent_id: "completed" for a in phase.agents},
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
def _evaluate_gate(self, gate: Gate) -> GateResult:
|
|
188
|
+
"""Evaluate a phase gate."""
|
|
189
|
+
if gate.type == GateType.AUTO:
|
|
190
|
+
return GateResult(passed=True, gate_type=GateType.AUTO, message="Auto-pass")
|
|
191
|
+
|
|
192
|
+
if self._on_gate_check:
|
|
193
|
+
return self._on_gate_check(gate)
|
|
194
|
+
|
|
195
|
+
# Default: pass
|
|
196
|
+
return GateResult(passed=True, gate_type=gate.type, message="Default pass")
|
|
197
|
+
|
|
198
|
+
def _evaluate_condition(self, condition: str) -> bool:
|
|
199
|
+
"""Evaluate a skip/branch condition.
|
|
200
|
+
|
|
201
|
+
For safety, only evaluates simple boolean expressions.
|
|
202
|
+
"""
|
|
203
|
+
# In production, this would evaluate against workflow context
|
|
204
|
+
return False
|
|
205
|
+
|
|
206
|
+
def _is_phase_complete(self, workflow: Workflow, phase_id: str) -> bool:
|
|
207
|
+
"""Check if a specific phase is complete."""
|
|
208
|
+
phase = workflow.get_phase_by_id(phase_id)
|
|
209
|
+
if phase is None:
|
|
210
|
+
return False
|
|
211
|
+
return phase.status in (PhaseStatus.COMPLETED, PhaseStatus.SKIPPED)
|
|
212
|
+
|
|
213
|
+
@property
|
|
214
|
+
def history(self) -> list[PhaseResult]:
|
|
215
|
+
"""Get the execution history."""
|
|
216
|
+
return self._history
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Workflow YAML loader."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import yaml
|
|
5
|
+
|
|
6
|
+
from core.workflow.schema import Workflow
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def load_workflow(path: str | Path) -> Workflow:
|
|
10
|
+
"""Load a workflow from a YAML file.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
path: Path to the workflow YAML file.
|
|
14
|
+
|
|
15
|
+
Returns:
|
|
16
|
+
Validated Workflow instance.
|
|
17
|
+
"""
|
|
18
|
+
path = Path(path)
|
|
19
|
+
if not path.exists():
|
|
20
|
+
raise FileNotFoundError(f"Workflow file not found: {path}")
|
|
21
|
+
|
|
22
|
+
with open(path) as f:
|
|
23
|
+
data = yaml.safe_load(f)
|
|
24
|
+
|
|
25
|
+
if data is None:
|
|
26
|
+
raise ValueError(f"Empty workflow file: {path}")
|
|
27
|
+
|
|
28
|
+
return Workflow.model_validate(data)
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""Workflow schema — Pydantic models for declarative YAML workflows.
|
|
2
|
+
|
|
3
|
+
Workflows define multi-phase execution plans with:
|
|
4
|
+
- Sequential phases with assigned agents
|
|
5
|
+
- Gates between phases (user approval, quality check, auto)
|
|
6
|
+
- Conditions for skipping or branching
|
|
7
|
+
- Parallel execution of independent agents within a phase
|
|
8
|
+
- Quality Gate integration (mandatory for all departments)
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from enum import Enum
|
|
12
|
+
from typing import Optional, Any
|
|
13
|
+
from pydantic import BaseModel, Field
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class PhaseStatus(str, Enum):
|
|
17
|
+
PENDING = "pending"
|
|
18
|
+
IN_PROGRESS = "in_progress"
|
|
19
|
+
COMPLETED = "completed"
|
|
20
|
+
SKIPPED = "skipped"
|
|
21
|
+
FAILED = "failed"
|
|
22
|
+
BLOCKED = "blocked"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class GateType(str, Enum):
|
|
26
|
+
USER_APPROVAL = "user_approval" # Requires user to confirm
|
|
27
|
+
QUALITY_GATE = "quality_gate" # Marta + Eduardo + Francisca
|
|
28
|
+
AUTO = "auto" # Passes automatically if phase succeeds
|
|
29
|
+
CONDITION = "condition" # Passes if condition evaluates true
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Gate(BaseModel):
|
|
33
|
+
"""A gate between phases — controls flow progression."""
|
|
34
|
+
type: GateType = GateType.AUTO
|
|
35
|
+
description: str = ""
|
|
36
|
+
condition: Optional[str] = None # Python expression for CONDITION type
|
|
37
|
+
required_verdict: str = "APPROVED" # For QUALITY_GATE type
|
|
38
|
+
timeout_seconds: int = 0 # 0 = no timeout
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class AgentAssignment(BaseModel):
|
|
42
|
+
"""An agent assigned to work within a phase."""
|
|
43
|
+
agent_id: str
|
|
44
|
+
role: str = "" # What this agent does in this phase
|
|
45
|
+
parallel: bool = False # Can run in parallel with other agents
|
|
46
|
+
optional: bool = False # Phase can complete without this agent
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class PhaseOutput(BaseModel):
|
|
50
|
+
"""Expected output from a phase."""
|
|
51
|
+
type: str = "document" # document, code, review, decision
|
|
52
|
+
format: str = "" # markdown, yaml, json, code
|
|
53
|
+
obsidian_path: str = "" # Where to save in Obsidian vault
|
|
54
|
+
description: str = ""
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class Phase(BaseModel):
|
|
58
|
+
"""A single phase in a workflow."""
|
|
59
|
+
id: str
|
|
60
|
+
name: str
|
|
61
|
+
description: str = ""
|
|
62
|
+
agents: list[AgentAssignment] = Field(default_factory=list)
|
|
63
|
+
gate: Gate = Field(default_factory=Gate)
|
|
64
|
+
outputs: list[PhaseOutput] = Field(default_factory=list)
|
|
65
|
+
depends_on: list[str] = Field(default_factory=list)
|
|
66
|
+
skip_if: Optional[str] = None # Condition to skip this phase
|
|
67
|
+
status: PhaseStatus = PhaseStatus.PENDING
|
|
68
|
+
result: Optional[str] = None
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class WorkflowTier(str, Enum):
|
|
72
|
+
ENTERPRISE = "enterprise" # Full 7-10 phase workflow
|
|
73
|
+
FOCUSED = "focused" # 3-4 phases for medium tasks
|
|
74
|
+
SPECIALIST = "specialist" # 1-2 phases for simple tasks
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class Workflow(BaseModel):
|
|
78
|
+
"""Complete workflow definition.
|
|
79
|
+
|
|
80
|
+
A workflow is a sequence of phases with gates between them.
|
|
81
|
+
Each phase has assigned agents and expected outputs.
|
|
82
|
+
Quality Gate (Phase N-1) is mandatory for all workflows.
|
|
83
|
+
"""
|
|
84
|
+
id: str
|
|
85
|
+
name: str
|
|
86
|
+
description: str = ""
|
|
87
|
+
department: str
|
|
88
|
+
tier: WorkflowTier = WorkflowTier.ENTERPRISE
|
|
89
|
+
command: str = "" # The CLI command that triggers this
|
|
90
|
+
|
|
91
|
+
phases: list[Phase] = Field(default_factory=list)
|
|
92
|
+
|
|
93
|
+
# Workflow-level config
|
|
94
|
+
requires_branch: bool = False # Must run on feature branch
|
|
95
|
+
requires_spec: bool = False # Must have approved spec first
|
|
96
|
+
quality_gate_required: bool = True # Quality Gate phase mandatory
|
|
97
|
+
max_duration_minutes: int = 0 # 0 = no limit
|
|
98
|
+
|
|
99
|
+
# Runtime state
|
|
100
|
+
current_phase: int = 0
|
|
101
|
+
status: PhaseStatus = PhaseStatus.PENDING
|
|
102
|
+
|
|
103
|
+
def get_current_phase(self) -> Optional[Phase]:
|
|
104
|
+
"""Get the currently active phase."""
|
|
105
|
+
if 0 <= self.current_phase < len(self.phases):
|
|
106
|
+
return self.phases[self.current_phase]
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
def get_phase_by_id(self, phase_id: str) -> Optional[Phase]:
|
|
110
|
+
"""Find a phase by its ID."""
|
|
111
|
+
for phase in self.phases:
|
|
112
|
+
if phase.id == phase_id:
|
|
113
|
+
return phase
|
|
114
|
+
return None
|
|
115
|
+
|
|
116
|
+
def all_phases_complete(self) -> bool:
|
|
117
|
+
"""Check if all phases are completed or skipped."""
|
|
118
|
+
return all(
|
|
119
|
+
p.status in (PhaseStatus.COMPLETED, PhaseStatus.SKIPPED)
|
|
120
|
+
for p in self.phases
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
def next_phase(self) -> Optional[Phase]:
|
|
124
|
+
"""Get the next pending phase."""
|
|
125
|
+
for i, phase in enumerate(self.phases):
|
|
126
|
+
if phase.status == PhaseStatus.PENDING:
|
|
127
|
+
self.current_phase = i
|
|
128
|
+
return phase
|
|
129
|
+
return None
|