@planu/cli 1.12.0 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/ai-tool-registry.json +71 -0
- package/dist/config/autopilot-config.json +21 -0
- package/dist/config/competitive-catalog.json +83 -0
- package/dist/config/license-plans.json +17 -1
- package/dist/engine/agent-registry/lifecycle-manager.d.ts +8 -0
- package/dist/engine/agent-registry/lifecycle-manager.d.ts.map +1 -0
- package/dist/engine/agent-registry/lifecycle-manager.js +81 -0
- package/dist/engine/agent-registry/lifecycle-manager.js.map +1 -0
- package/dist/engine/agent-registry/role-catalog.d.ts +17 -0
- package/dist/engine/agent-registry/role-catalog.d.ts.map +1 -0
- package/dist/engine/agent-registry/role-catalog.js +55 -0
- package/dist/engine/agent-registry/role-catalog.js.map +1 -0
- package/dist/engine/autopilot/action-executor.d.ts +18 -0
- package/dist/engine/autopilot/action-executor.d.ts.map +1 -0
- package/dist/engine/autopilot/action-executor.js +91 -0
- package/dist/engine/autopilot/action-executor.js.map +1 -0
- package/dist/engine/autopilot/event-bus.d.ts +8 -0
- package/dist/engine/autopilot/event-bus.d.ts.map +1 -0
- package/dist/engine/autopilot/event-bus.js +28 -0
- package/dist/engine/autopilot/event-bus.js.map +1 -0
- package/dist/engine/autopilot/trigger-rules.d.ts +3 -0
- package/dist/engine/autopilot/trigger-rules.d.ts.map +1 -0
- package/dist/engine/autopilot/trigger-rules.js +125 -0
- package/dist/engine/autopilot/trigger-rules.js.map +1 -0
- package/dist/engine/competitive/gap-analyzer.d.ts +12 -0
- package/dist/engine/competitive/gap-analyzer.d.ts.map +1 -0
- package/dist/engine/competitive/gap-analyzer.js +214 -0
- package/dist/engine/competitive/gap-analyzer.js.map +1 -0
- package/dist/engine/hook-generator/ai-hook-templates.d.ts +8 -0
- package/dist/engine/hook-generator/ai-hook-templates.d.ts.map +1 -0
- package/dist/engine/hook-generator/ai-hook-templates.js +43 -0
- package/dist/engine/hook-generator/ai-hook-templates.js.map +1 -0
- package/dist/engine/hook-generator/hook-merger.d.ts +13 -0
- package/dist/engine/hook-generator/hook-merger.d.ts.map +1 -0
- package/dist/engine/hook-generator/hook-merger.js +148 -0
- package/dist/engine/hook-generator/hook-merger.js.map +1 -0
- package/dist/engine/hook-generator/stack-hook-templates.d.ts +10 -0
- package/dist/engine/hook-generator/stack-hook-templates.d.ts.map +1 -0
- package/dist/engine/hook-generator/stack-hook-templates.js +105 -0
- package/dist/engine/hook-generator/stack-hook-templates.js.map +1 -0
- package/dist/engine/project-dna/ai-tool-detector.d.ts +12 -0
- package/dist/engine/project-dna/ai-tool-detector.d.ts.map +1 -0
- package/dist/engine/project-dna/ai-tool-detector.js +103 -0
- package/dist/engine/project-dna/ai-tool-detector.js.map +1 -0
- package/dist/engine/project-dna/rules-generator.d.ts +18 -0
- package/dist/engine/project-dna/rules-generator.d.ts.map +1 -0
- package/dist/engine/project-dna/rules-generator.js +193 -0
- package/dist/engine/project-dna/rules-generator.js.map +1 -0
- package/dist/engine/project-dna/stack-detector.d.ts +24 -0
- package/dist/engine/project-dna/stack-detector.d.ts.map +1 -0
- package/dist/engine/project-dna/stack-detector.js +309 -0
- package/dist/engine/project-dna/stack-detector.js.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/storage/agent-registry-store.d.ts +11 -0
- package/dist/storage/agent-registry-store.d.ts.map +1 -0
- package/dist/storage/agent-registry-store.js +45 -0
- package/dist/storage/agent-registry-store.js.map +1 -0
- package/dist/tools/competitive-handlers.d.ts +30 -0
- package/dist/tools/competitive-handlers.d.ts.map +1 -0
- package/dist/tools/competitive-handlers.js +155 -0
- package/dist/tools/competitive-handlers.js.map +1 -0
- package/dist/tools/create-spec/post-creation.d.ts +1 -1
- package/dist/tools/create-spec/post-creation.d.ts.map +1 -1
- package/dist/tools/create-spec/post-creation.js +13 -1
- package/dist/tools/create-spec/post-creation.js.map +1 -1
- package/dist/tools/create-spec.js +1 -1
- package/dist/tools/create-spec.js.map +1 -1
- package/dist/tools/hook-generator-handler.d.ts +8 -0
- package/dist/tools/hook-generator-handler.d.ts.map +1 -0
- package/dist/tools/hook-generator-handler.js +154 -0
- package/dist/tools/hook-generator-handler.js.map +1 -0
- package/dist/tools/project-dna-handler.d.ts +34 -0
- package/dist/tools/project-dna-handler.d.ts.map +1 -0
- package/dist/tools/project-dna-handler.js +261 -0
- package/dist/tools/project-dna-handler.js.map +1 -0
- package/dist/tools/register-agent-registry.d.ts +5 -0
- package/dist/tools/register-agent-registry.d.ts.map +1 -0
- package/dist/tools/register-agent-registry.js +254 -0
- package/dist/tools/register-agent-registry.js.map +1 -0
- package/dist/tools/register-autopilot.d.ts +3 -0
- package/dist/tools/register-autopilot.d.ts.map +1 -0
- package/dist/tools/register-autopilot.js +78 -0
- package/dist/tools/register-autopilot.js.map +1 -0
- package/dist/tools/register-competitive.d.ts +3 -0
- package/dist/tools/register-competitive.d.ts.map +1 -0
- package/dist/tools/register-competitive.js +88 -0
- package/dist/tools/register-competitive.js.map +1 -0
- package/dist/tools/register-hook-generator.d.ts +3 -0
- package/dist/tools/register-hook-generator.d.ts.map +1 -0
- package/dist/tools/register-hook-generator.js +96 -0
- package/dist/tools/register-hook-generator.js.map +1 -0
- package/dist/tools/register-project-dna.d.ts +3 -0
- package/dist/tools/register-project-dna.d.ts.map +1 -0
- package/dist/tools/register-project-dna.js +43 -0
- package/dist/tools/register-project-dna.js.map +1 -0
- package/dist/tools/update-status/side-effects.d.ts.map +1 -1
- package/dist/tools/update-status/side-effects.js +32 -0
- package/dist/tools/update-status/side-effects.js.map +1 -1
- package/dist/types/agent-registry.d.ts +53 -0
- package/dist/types/agent-registry.d.ts.map +1 -0
- package/dist/types/agent-registry.js +2 -0
- package/dist/types/agent-registry.js.map +1 -0
- package/dist/types/autopilot.d.ts +36 -0
- package/dist/types/autopilot.d.ts.map +1 -0
- package/dist/types/autopilot.js +3 -0
- package/dist/types/autopilot.js.map +1 -0
- package/dist/types/competitive.d.ts +41 -0
- package/dist/types/competitive.d.ts.map +1 -0
- package/dist/types/competitive.js +3 -0
- package/dist/types/competitive.js.map +1 -0
- package/dist/types/hook-generator.d.ts +49 -0
- package/dist/types/hook-generator.d.ts.map +1 -0
- package/dist/types/hook-generator.js +3 -0
- package/dist/types/hook-generator.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/project-dna.d.ts +46 -0
- package/dist/types/project-dna.d.ts.map +1 -0
- package/dist/types/project-dna.js +4 -0
- package/dist/types/project-dna.js.map +1 -0
- package/package.json +1 -1
- package/src/config/ai-tool-registry.json +71 -0
- package/src/config/autopilot-config.json +21 -0
- package/src/config/competitive-catalog.json +83 -0
- package/src/config/license-plans.json +17 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"tools": {
|
|
4
|
+
"claude": {
|
|
5
|
+
"id": "claude",
|
|
6
|
+
"name": "Claude Code",
|
|
7
|
+
"detectionFiles": ["CLAUDE.md", ".claude/"],
|
|
8
|
+
"rulesDir": ".claude/rules/",
|
|
9
|
+
"rulesFormat": "markdown",
|
|
10
|
+
"docsUrl": "https://platform.claude.com/docs/en/home",
|
|
11
|
+
"configFile": "CLAUDE.md"
|
|
12
|
+
},
|
|
13
|
+
"cursor": {
|
|
14
|
+
"id": "cursor",
|
|
15
|
+
"name": "Cursor",
|
|
16
|
+
"detectionFiles": [".cursor/", ".cursorignore"],
|
|
17
|
+
"rulesDir": ".cursor/rules/",
|
|
18
|
+
"rulesFormat": "mdc",
|
|
19
|
+
"docsUrl": "https://docs.cursor.com/context/rules",
|
|
20
|
+
"frontmatterRequired": true
|
|
21
|
+
},
|
|
22
|
+
"windsurf": {
|
|
23
|
+
"id": "windsurf",
|
|
24
|
+
"name": "Windsurf",
|
|
25
|
+
"detectionFiles": [".windsurfrules"],
|
|
26
|
+
"rulesFile": ".windsurfrules",
|
|
27
|
+
"rulesFormat": "markdown-append",
|
|
28
|
+
"docsUrl": "https://docs.windsurf.com/windsurf/memories-and-rules"
|
|
29
|
+
},
|
|
30
|
+
"gemini": {
|
|
31
|
+
"id": "gemini",
|
|
32
|
+
"name": "Gemini CLI",
|
|
33
|
+
"detectionFiles": ["GEMINI.md", ".gemini/"],
|
|
34
|
+
"configFile": "GEMINI.md",
|
|
35
|
+
"rulesFormat": "markdown",
|
|
36
|
+
"docsUrl": "https://ai.google.dev/gemini-api/docs"
|
|
37
|
+
},
|
|
38
|
+
"kiro": {
|
|
39
|
+
"id": "kiro",
|
|
40
|
+
"name": "Kiro (AWS)",
|
|
41
|
+
"detectionFiles": [".kiro/"],
|
|
42
|
+
"rulesDir": ".kiro/steering/",
|
|
43
|
+
"rulesFormat": "markdown",
|
|
44
|
+
"docsUrl": "https://kiro.dev/docs/steering-files"
|
|
45
|
+
},
|
|
46
|
+
"cline": {
|
|
47
|
+
"id": "cline",
|
|
48
|
+
"name": "Cline",
|
|
49
|
+
"detectionFiles": [".clinerules"],
|
|
50
|
+
"rulesFile": ".clinerules",
|
|
51
|
+
"rulesFormat": "markdown-append",
|
|
52
|
+
"docsUrl": "https://github.com/cline/cline"
|
|
53
|
+
},
|
|
54
|
+
"copilot": {
|
|
55
|
+
"id": "copilot",
|
|
56
|
+
"name": "GitHub Copilot",
|
|
57
|
+
"detectionFiles": [".github/copilot-instructions.md"],
|
|
58
|
+
"rulesFile": ".github/copilot-instructions.md",
|
|
59
|
+
"rulesFormat": "markdown-append",
|
|
60
|
+
"docsUrl": "https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot"
|
|
61
|
+
},
|
|
62
|
+
"aider": {
|
|
63
|
+
"id": "aider",
|
|
64
|
+
"name": "Aider",
|
|
65
|
+
"detectionFiles": [".aider.conf.yml", ".aiderignore"],
|
|
66
|
+
"configFile": ".aider.conf.yml",
|
|
67
|
+
"rulesFormat": "yaml",
|
|
68
|
+
"docsUrl": "https://aider.chat/docs/config/aider_conf.html"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"rules": {
|
|
4
|
+
"post-create:validate_criteria_quality": { "enabled": true },
|
|
5
|
+
"post-create:suggest_criteria": { "enabled": true },
|
|
6
|
+
"post-create:detect_contradictions": { "enabled": true },
|
|
7
|
+
"post-approved:challenge_spec": { "enabled": true, "threshold": 20 },
|
|
8
|
+
"post-approved:spec_quality_score": { "enabled": true },
|
|
9
|
+
"post-approved:generate_orchestration_plan": { "enabled": true, "threshold": 20 },
|
|
10
|
+
"post-implementing:tdd_scaffold": { "enabled": true },
|
|
11
|
+
"post-implementing:watch_spec_drift_start": { "enabled": true },
|
|
12
|
+
"post-done:watch_spec_drift_stop": { "enabled": true },
|
|
13
|
+
"post-done:auto_fix_health": { "enabled": true },
|
|
14
|
+
"post-done:generate_changelog": { "enabled": true },
|
|
15
|
+
"drift-detected:resolve_drift_violations": { "enabled": true },
|
|
16
|
+
"drift-detected:log_lesson": { "enabled": true },
|
|
17
|
+
"cron:health_check_all": { "enabled": false },
|
|
18
|
+
"cron:velocity_report": { "enabled": false },
|
|
19
|
+
"cron:estimation_accuracy_report": { "enabled": false }
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"updatedAt": "2026-04-08",
|
|
4
|
+
"competitors": {
|
|
5
|
+
"kiro": {
|
|
6
|
+
"id": "kiro",
|
|
7
|
+
"name": "Kiro (AWS)",
|
|
8
|
+
"url": "https://kiro.dev",
|
|
9
|
+
"capabilities": [
|
|
10
|
+
"steering-files",
|
|
11
|
+
"spec-system",
|
|
12
|
+
"ai-hooks",
|
|
13
|
+
"requirements-tracking",
|
|
14
|
+
"acceptance-criteria",
|
|
15
|
+
"agent-loops"
|
|
16
|
+
],
|
|
17
|
+
"strengths": ["AWS integration", "agent-native workflow", "hooks system"],
|
|
18
|
+
"weaknesses": ["no drift detection", "no compliance reporting", "no multi-language docs", "no velocity metrics"],
|
|
19
|
+
"updatedAt": "2026-04-08"
|
|
20
|
+
},
|
|
21
|
+
"tessl": {
|
|
22
|
+
"id": "tessl",
|
|
23
|
+
"name": "Tessl",
|
|
24
|
+
"url": "https://tessl.io",
|
|
25
|
+
"capabilities": ["ai-requirements", "natural-language-specs", "test-generation"],
|
|
26
|
+
"strengths": ["natural language input", "AI-first design"],
|
|
27
|
+
"weaknesses": ["no MCP protocol", "no drift detection", "no license tiers", "no competitive analysis"],
|
|
28
|
+
"updatedAt": "2026-04-08"
|
|
29
|
+
},
|
|
30
|
+
"github-spec-kit": {
|
|
31
|
+
"id": "github-spec-kit",
|
|
32
|
+
"name": "GitHub spec-kit",
|
|
33
|
+
"url": "https://github.com",
|
|
34
|
+
"capabilities": ["spec-templates", "github-integration", "pr-linking"],
|
|
35
|
+
"strengths": ["GitHub native", "free", "simple"],
|
|
36
|
+
"weaknesses": ["no AI analysis", "no drift detection", "no compliance", "no metrics", "manual only"],
|
|
37
|
+
"updatedAt": "2026-04-08"
|
|
38
|
+
},
|
|
39
|
+
"linear": {
|
|
40
|
+
"id": "linear",
|
|
41
|
+
"name": "Linear",
|
|
42
|
+
"url": "https://linear.app",
|
|
43
|
+
"capabilities": ["issue-tracking", "sprint-planning", "ai-writing", "roadmaps", "velocity-metrics"],
|
|
44
|
+
"strengths": ["excellent UX", "fast", "team-oriented"],
|
|
45
|
+
"weaknesses": ["no spec-driven dev", "no drift detection", "no AI code alignment", "no compliance"],
|
|
46
|
+
"updatedAt": "2026-04-08"
|
|
47
|
+
},
|
|
48
|
+
"jira": {
|
|
49
|
+
"id": "jira",
|
|
50
|
+
"name": "Jira (Atlassian)",
|
|
51
|
+
"url": "https://atlassian.com/jira",
|
|
52
|
+
"capabilities": [
|
|
53
|
+
"issue-tracking",
|
|
54
|
+
"sprint-planning",
|
|
55
|
+
"roadmaps",
|
|
56
|
+
"reporting",
|
|
57
|
+
"integrations",
|
|
58
|
+
"custom-workflows"
|
|
59
|
+
],
|
|
60
|
+
"strengths": ["enterprise adoption", "integrations ecosystem", "customizable"],
|
|
61
|
+
"weaknesses": ["no AI spec alignment", "no drift detection", "slow", "complex setup", "no MCP"],
|
|
62
|
+
"updatedAt": "2026-04-08"
|
|
63
|
+
},
|
|
64
|
+
"notion": {
|
|
65
|
+
"id": "notion",
|
|
66
|
+
"name": "Notion",
|
|
67
|
+
"url": "https://notion.so",
|
|
68
|
+
"capabilities": ["docs", "lightweight-specs", "databases", "ai-writing", "templates"],
|
|
69
|
+
"strengths": ["flexible", "good UX", "AI writing"],
|
|
70
|
+
"weaknesses": ["no code alignment", "no drift detection", "no metrics", "no MCP", "manual tracking"],
|
|
71
|
+
"updatedAt": "2026-04-08"
|
|
72
|
+
},
|
|
73
|
+
"shortcut": {
|
|
74
|
+
"id": "shortcut",
|
|
75
|
+
"name": "Shortcut (ex-Clubhouse)",
|
|
76
|
+
"url": "https://shortcut.com",
|
|
77
|
+
"capabilities": ["story-tracking", "roadmaps", "velocity-metrics", "git-integration"],
|
|
78
|
+
"strengths": ["developer-friendly", "git integration", "clean UX"],
|
|
79
|
+
"weaknesses": ["no AI spec alignment", "no drift detection", "no compliance", "no MCP"],
|
|
80
|
+
"updatedAt": "2026-04-08"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -95,7 +95,12 @@
|
|
|
95
95
|
"security_scan",
|
|
96
96
|
"set_context_profile",
|
|
97
97
|
"get_context_profile",
|
|
98
|
-
"list_context_profiles"
|
|
98
|
+
"list_context_profiles",
|
|
99
|
+
"list_competitors",
|
|
100
|
+
"detect_project_dna",
|
|
101
|
+
"list_agents",
|
|
102
|
+
"agent_health",
|
|
103
|
+
"preview_hooks"
|
|
99
104
|
],
|
|
100
105
|
"proTools": [
|
|
101
106
|
"a2a_delegate",
|
|
@@ -437,6 +442,17 @@
|
|
|
437
442
|
"federation_discovery_status",
|
|
438
443
|
"dogfood_status",
|
|
439
444
|
"generate_compliance_evidence",
|
|
445
|
+
"competitive_gap_analysis",
|
|
446
|
+
"update_competitive_catalog",
|
|
447
|
+
"configure_autopilot",
|
|
448
|
+
"bootstrap_project_intelligence",
|
|
449
|
+
"update_project_dna",
|
|
450
|
+
"register_agent",
|
|
451
|
+
"stop_agent",
|
|
452
|
+
"restart_agent",
|
|
453
|
+
"unregister_agent",
|
|
454
|
+
"generate_hooks_for_stack",
|
|
455
|
+
"merge_hooks",
|
|
440
456
|
"check_api_compatibility_v2",
|
|
441
457
|
"critical_path_analyzer_v2",
|
|
442
458
|
"similar_problems_finder_v2",
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PersistentAgent, RegistryAgentRole, AgentTriggerConfig, AgentRegistryHealthResult } from '../../types/index.js';
|
|
2
|
+
export declare function registerAgent(projectPath: string, role: RegistryAgentRole, trigger: AgentTriggerConfig, config: Record<string, unknown>): Promise<PersistentAgent>;
|
|
3
|
+
export declare function stopAgent(projectPath: string, role: RegistryAgentRole): Promise<void>;
|
|
4
|
+
export declare function restartAgent(projectPath: string, role: RegistryAgentRole): Promise<PersistentAgent>;
|
|
5
|
+
export declare function unregisterAgent(projectPath: string, role: RegistryAgentRole): Promise<void>;
|
|
6
|
+
export declare function getAgentHealth(projectPath: string, role: RegistryAgentRole): Promise<AgentRegistryHealthResult>;
|
|
7
|
+
export declare function listAllAgents(projectPath: string): Promise<PersistentAgent[]>;
|
|
8
|
+
//# sourceMappingURL=lifecycle-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle-manager.d.ts","sourceRoot":"","sources":["../../../src/engine/agent-registry/lifecycle-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,EAC1B,MAAM,sBAAsB,CAAC;AAG9B,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,iBAAiB,EACvB,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,eAAe,CAAC,CAmB1B;AAED,wBAAsB,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAU3F;AAED,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,eAAe,CAAC,CAW1B;AAED,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CASjG;AAED,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,yBAAyB,CAAC,CAiCpC;AAED,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAInF"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Lógica de register/stop/restart/unregister para agentes persistentes
|
|
2
|
+
import { AgentRegistryStore } from '../../storage/agent-registry-store.js';
|
|
3
|
+
export async function registerAgent(projectPath, role, trigger, config) {
|
|
4
|
+
const store = new AgentRegistryStore(projectPath);
|
|
5
|
+
const existing = await store.getAgent(role);
|
|
6
|
+
const agent = {
|
|
7
|
+
role,
|
|
8
|
+
trigger,
|
|
9
|
+
status: 'active',
|
|
10
|
+
registeredAt: existing?.registeredAt ?? new Date().toISOString(),
|
|
11
|
+
lastRunAt: existing?.lastRunAt,
|
|
12
|
+
nextRunAt: existing?.nextRunAt,
|
|
13
|
+
runCount: existing?.runCount ?? 0,
|
|
14
|
+
successCount: existing?.successCount ?? 0,
|
|
15
|
+
recentRuns: existing?.recentRuns ?? [],
|
|
16
|
+
config,
|
|
17
|
+
};
|
|
18
|
+
await store.upsertAgent(agent);
|
|
19
|
+
return agent;
|
|
20
|
+
}
|
|
21
|
+
export async function stopAgent(projectPath, role) {
|
|
22
|
+
const store = new AgentRegistryStore(projectPath);
|
|
23
|
+
const agent = await store.getAgent(role);
|
|
24
|
+
if (agent === undefined) {
|
|
25
|
+
throw new Error(`Agent '${role}' is not registered in this project`);
|
|
26
|
+
}
|
|
27
|
+
agent.status = 'paused';
|
|
28
|
+
await store.upsertAgent(agent);
|
|
29
|
+
}
|
|
30
|
+
export async function restartAgent(projectPath, role) {
|
|
31
|
+
const store = new AgentRegistryStore(projectPath);
|
|
32
|
+
const agent = await store.getAgent(role);
|
|
33
|
+
if (agent === undefined) {
|
|
34
|
+
throw new Error(`Agent '${role}' is not registered in this project`);
|
|
35
|
+
}
|
|
36
|
+
agent.status = 'active';
|
|
37
|
+
await store.upsertAgent(agent);
|
|
38
|
+
return agent;
|
|
39
|
+
}
|
|
40
|
+
export async function unregisterAgent(projectPath, role) {
|
|
41
|
+
const store = new AgentRegistryStore(projectPath);
|
|
42
|
+
const agent = await store.getAgent(role);
|
|
43
|
+
if (agent === undefined) {
|
|
44
|
+
throw new Error(`Agent '${role}' is not registered in this project`);
|
|
45
|
+
}
|
|
46
|
+
await store.removeAgent(role);
|
|
47
|
+
}
|
|
48
|
+
export async function getAgentHealth(projectPath, role) {
|
|
49
|
+
const store = new AgentRegistryStore(projectPath);
|
|
50
|
+
const agent = await store.getAgent(role);
|
|
51
|
+
if (agent === undefined) {
|
|
52
|
+
return {
|
|
53
|
+
role,
|
|
54
|
+
status: 'unregistered',
|
|
55
|
+
successRate: 0,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const successRate = agent.runCount > 0 ? agent.successCount / agent.runCount : 0;
|
|
59
|
+
const completedRuns = agent.recentRuns.filter((r) => r.durationMs !== undefined);
|
|
60
|
+
const avgDurationMs = completedRuns.length > 0
|
|
61
|
+
? completedRuns.reduce((sum, r) => sum + (r.durationMs ?? 0), 0) / completedRuns.length
|
|
62
|
+
: undefined;
|
|
63
|
+
const lastFailed = agent.recentRuns
|
|
64
|
+
.slice()
|
|
65
|
+
.reverse()
|
|
66
|
+
.find((r) => !r.success);
|
|
67
|
+
return {
|
|
68
|
+
role,
|
|
69
|
+
status: agent.status,
|
|
70
|
+
lastRunAt: agent.lastRunAt,
|
|
71
|
+
successRate,
|
|
72
|
+
avgDurationMs,
|
|
73
|
+
lastError: lastFailed?.error,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
export async function listAllAgents(projectPath) {
|
|
77
|
+
const store = new AgentRegistryStore(projectPath);
|
|
78
|
+
const registry = await store.load();
|
|
79
|
+
return Object.values(registry.agents);
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=lifecycle-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle-manager.js","sourceRoot":"","sources":["../../../src/engine/agent-registry/lifecycle-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { RegistryAgentRole } from '../../types/index.js';
|
|
2
|
+
export interface RoleDef {
|
|
3
|
+
role: RegistryAgentRole;
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
defaultTrigger: {
|
|
7
|
+
type: string;
|
|
8
|
+
schedule?: string;
|
|
9
|
+
event?: string;
|
|
10
|
+
webhook?: string;
|
|
11
|
+
};
|
|
12
|
+
defaultConfig: Record<string, unknown>;
|
|
13
|
+
requiredTools: string[];
|
|
14
|
+
}
|
|
15
|
+
export declare const ROLE_CATALOG: RoleDef[];
|
|
16
|
+
export declare function getRoleDef(role: RegistryAgentRole): RoleDef | undefined;
|
|
17
|
+
//# sourceMappingURL=role-catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role-catalog.d.ts","sourceRoot":"","sources":["../../../src/engine/agent-registry/role-catalog.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAG9D,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtF,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,eAAO,MAAM,YAAY,EAAE,OAAO,EAkDjC,CAAC;AAEF,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,GAAG,SAAS,CAEvE"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Catálogo de roles predefinidos con su descripción y config por defecto
|
|
2
|
+
export const ROLE_CATALOG = [
|
|
3
|
+
{
|
|
4
|
+
role: 'spec-guardian',
|
|
5
|
+
name: 'Spec Guardian',
|
|
6
|
+
description: 'Monitors drift in implementing/done specs and alerts when score exceeds threshold',
|
|
7
|
+
defaultTrigger: { type: 'cron', schedule: '0 9 * * *' },
|
|
8
|
+
defaultConfig: { driftThreshold: 0.3, notifyOnDetection: true },
|
|
9
|
+
requiredTools: ['detect_drift', 'resolve_drift_violations'],
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
role: 'pr-reviewer',
|
|
13
|
+
name: 'PR Reviewer',
|
|
14
|
+
description: 'Auto-reviews PRs when opened and posts spec compliance feedback',
|
|
15
|
+
defaultTrigger: { type: 'webhook', webhook: 'github:pull_request.opened' },
|
|
16
|
+
defaultConfig: { blockOnLowScore: false, minComplianceScore: 70 },
|
|
17
|
+
requiredTools: ['review_pr', 'verify_spec_compliance'],
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
role: 'metrics-analyst',
|
|
21
|
+
name: 'Metrics Analyst',
|
|
22
|
+
description: 'Generates weekly velocity and estimation accuracy reports',
|
|
23
|
+
defaultTrigger: { type: 'cron', schedule: '0 9 * * 1' },
|
|
24
|
+
defaultConfig: { includeVelocity: true, includeEstimationAccuracy: true },
|
|
25
|
+
requiredTools: ['velocity_report', 'estimation_accuracy_report'],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
role: 'criteria-auditor',
|
|
29
|
+
name: 'Criteria Auditor',
|
|
30
|
+
description: 'Validates EARS quality of new spec criteria automatically',
|
|
31
|
+
defaultTrigger: { type: 'event', event: 'spec:created' },
|
|
32
|
+
defaultConfig: { minEarsScore: 70, suggestRewrite: true },
|
|
33
|
+
requiredTools: ['validate_criteria_quality', 'rewrite_criteria_ears'],
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
role: 'changelog-keeper',
|
|
37
|
+
name: 'Changelog Keeper',
|
|
38
|
+
description: 'Keeps CHANGELOG.md updated when specs are marked done',
|
|
39
|
+
defaultTrigger: { type: 'event', event: 'spec:status:done' },
|
|
40
|
+
defaultConfig: { format: 'keepachangelog' },
|
|
41
|
+
requiredTools: ['generate_changelog'],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
role: 'dependency-watcher',
|
|
45
|
+
name: 'Dependency Watcher',
|
|
46
|
+
description: 'Alerts when dependencies have known vulnerabilities or major updates',
|
|
47
|
+
defaultTrigger: { type: 'cron', schedule: '0 9 * * 1' },
|
|
48
|
+
defaultConfig: { alertOnVulnerability: true, alertOnMajorUpdate: false },
|
|
49
|
+
requiredTools: ['security_scan'],
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
export function getRoleDef(role) {
|
|
53
|
+
return ROLE_CATALOG.find((r) => r.role === role);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=role-catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role-catalog.js","sourceRoot":"","sources":["../../../src/engine/agent-registry/role-catalog.ts"],"names":[],"mappings":"AAAA,yEAAyE;AAczE,MAAM,CAAC,MAAM,YAAY,GAAc;IACrC;QACE,IAAI,EAAE,eAAe;QACrB,IAAI,EAAE,eAAe;QACrB,WAAW,EACT,mFAAmF;QACrF,cAAc,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE;QACvD,aAAa,EAAE,EAAE,cAAc,EAAE,GAAG,EAAE,iBAAiB,EAAE,IAAI,EAAE;QAC/D,aAAa,EAAE,CAAC,cAAc,EAAE,0BAA0B,CAAC;KAC5D;IACD;QACE,IAAI,EAAE,aAAa;QACnB,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,iEAAiE;QAC9E,cAAc,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,4BAA4B,EAAE;QAC1E,aAAa,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,kBAAkB,EAAE,EAAE,EAAE;QACjE,aAAa,EAAE,CAAC,WAAW,EAAE,wBAAwB,CAAC;KACvD;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,2DAA2D;QACxE,cAAc,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE;QACvD,aAAa,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,yBAAyB,EAAE,IAAI,EAAE;QACzE,aAAa,EAAE,CAAC,iBAAiB,EAAE,4BAA4B,CAAC;KACjE;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,IAAI,EAAE,kBAAkB;QACxB,WAAW,EAAE,2DAA2D;QACxE,cAAc,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE;QACxD,aAAa,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE;QACzD,aAAa,EAAE,CAAC,2BAA2B,EAAE,uBAAuB,CAAC;KACtE;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,IAAI,EAAE,kBAAkB;QACxB,WAAW,EAAE,uDAAuD;QACpE,cAAc,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE;QAC5D,aAAa,EAAE,EAAE,MAAM,EAAE,gBAAgB,EAAE;QAC3C,aAAa,EAAE,CAAC,oBAAoB,CAAC;KACtC;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EAAE,sEAAsE;QACnF,cAAc,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE;QACvD,aAAa,EAAE,EAAE,oBAAoB,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE;QACxE,aAAa,EAAE,CAAC,eAAe,CAAC;KACjC;CACF,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,IAAuB;IAChD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AutopilotEvent, AutopilotConfig, TriggerRule } from '../../types/index.js';
|
|
2
|
+
export declare function loadAutopilotConfig(projectPath: string): Promise<AutopilotConfig>;
|
|
3
|
+
export declare function saveAutopilotConfig(projectPath: string, config: AutopilotConfig): Promise<void>;
|
|
4
|
+
/**
|
|
5
|
+
* Executes all enabled trigger rules that match the given event.
|
|
6
|
+
* Each action is logged but never awaited — fire-and-forget.
|
|
7
|
+
*/
|
|
8
|
+
export declare function executeTriggersForEvent(event: AutopilotEvent): Promise<string[]>;
|
|
9
|
+
/**
|
|
10
|
+
* Returns the current autopilot status for a project.
|
|
11
|
+
*/
|
|
12
|
+
export declare function getAutopilotStatus(projectPath: string): Promise<{
|
|
13
|
+
totalRules: number;
|
|
14
|
+
enabledRules: number;
|
|
15
|
+
disabledRules: string[];
|
|
16
|
+
rules: TriggerRule[];
|
|
17
|
+
}>;
|
|
18
|
+
//# sourceMappingURL=action-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-executor.d.ts","sourceRoot":"","sources":["../../../src/engine/autopilot/action-executor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EAEf,WAAW,EACZ,MAAM,sBAAsB,CAAC;AAK9B,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAWvF;AAED,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,IAAI,CAAC,CAGf;AAgCD;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA4BtF;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB,CAAC,CAeD"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// engine/autopilot/action-executor.ts — SPEC-413: Executes trigger actions
|
|
2
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { DEFAULT_TRIGGER_RULES } from './trigger-rules.js';
|
|
5
|
+
const CONFIG_PATH_IN_PLANU = 'planu/autopilot-config.json';
|
|
6
|
+
export async function loadAutopilotConfig(projectPath) {
|
|
7
|
+
const localPath = join(projectPath, CONFIG_PATH_IN_PLANU);
|
|
8
|
+
try {
|
|
9
|
+
const raw = await readFile(localPath, 'utf-8');
|
|
10
|
+
return JSON.parse(raw);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
// Fall back to bundled defaults
|
|
14
|
+
const { createRequire } = await import('node:module');
|
|
15
|
+
const req = createRequire(import.meta.url);
|
|
16
|
+
return req('../../config/autopilot-config.json');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export async function saveAutopilotConfig(projectPath, config) {
|
|
20
|
+
const localPath = join(projectPath, CONFIG_PATH_IN_PLANU);
|
|
21
|
+
await writeFile(localPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
22
|
+
}
|
|
23
|
+
function conditionMet(condition, event) {
|
|
24
|
+
if (!condition) {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
const payload = event.payload ?? {};
|
|
28
|
+
if (condition.minEstimatedHours !== undefined) {
|
|
29
|
+
const hours = typeof payload.estimatedHours === 'number' ? payload.estimatedHours : 0;
|
|
30
|
+
if (hours < condition.minEstimatedHours) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (condition.riskLevel !== undefined) {
|
|
35
|
+
const risk = typeof payload.risk === 'string' ? payload.risk : '';
|
|
36
|
+
if (!condition.riskLevel.includes(risk)) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (condition.minDriftScore !== undefined) {
|
|
41
|
+
const score = typeof payload.driftScore === 'number' ? payload.driftScore : 0;
|
|
42
|
+
if (score < condition.minDriftScore) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Executes all enabled trigger rules that match the given event.
|
|
50
|
+
* Each action is logged but never awaited — fire-and-forget.
|
|
51
|
+
*/
|
|
52
|
+
export async function executeTriggersForEvent(event) {
|
|
53
|
+
const config = await loadAutopilotConfig(event.projectPath);
|
|
54
|
+
const triggered = [];
|
|
55
|
+
for (const rule of DEFAULT_TRIGGER_RULES) {
|
|
56
|
+
if (rule.event !== event.name) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
// Check config override
|
|
60
|
+
const ruleConfig = config.rules[rule.id];
|
|
61
|
+
const isEnabled = ruleConfig !== undefined ? ruleConfig.enabled : rule.enabled;
|
|
62
|
+
if (!isEnabled) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
// Check conditions
|
|
66
|
+
if (!conditionMet(rule.condition, event)) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
triggered.push(rule.action);
|
|
70
|
+
console.error(`[autopilot] triggered: ${rule.id} for ${event.name}${event.specId ? ` (${event.specId})` : ''}`);
|
|
71
|
+
}
|
|
72
|
+
return triggered;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Returns the current autopilot status for a project.
|
|
76
|
+
*/
|
|
77
|
+
export async function getAutopilotStatus(projectPath) {
|
|
78
|
+
const config = await loadAutopilotConfig(projectPath);
|
|
79
|
+
const rules = DEFAULT_TRIGGER_RULES.map((rule) => {
|
|
80
|
+
const override = config.rules[rule.id];
|
|
81
|
+
return { ...rule, enabled: override !== undefined ? override.enabled : rule.enabled };
|
|
82
|
+
});
|
|
83
|
+
const disabledRules = rules.filter((r) => !r.enabled).map((r) => r.id);
|
|
84
|
+
return {
|
|
85
|
+
totalRules: rules.length,
|
|
86
|
+
enabledRules: rules.filter((r) => r.enabled).length,
|
|
87
|
+
disabledRules,
|
|
88
|
+
rules,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=action-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-executor.js","sourceRoot":"","sources":["../../../src/engine/autopilot/action-executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AutopilotEvent, AutopilotEventName } from '../../types/index.js';
|
|
2
|
+
type EventHandler = (event: AutopilotEvent) => void;
|
|
3
|
+
export declare function onAutopilotEvent(name: AutopilotEventName, handler: EventHandler): void;
|
|
4
|
+
export declare function emitAutopilotEvent(event: AutopilotEvent): void;
|
|
5
|
+
/** Clears all handlers — used in tests */
|
|
6
|
+
export declare function clearAutopilotHandlers(): void;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=event-bus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../../src/engine/autopilot/event-bus.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG/E,KAAK,YAAY,GAAG,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;AAIpD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CAItF;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAe9D;AAED,0CAA0C;AAC1C,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// engine/autopilot/event-bus.ts — SPEC-413: Simple in-memory event bus for autopilot triggers
|
|
2
|
+
const handlers = new Map();
|
|
3
|
+
export function onAutopilotEvent(name, handler) {
|
|
4
|
+
const existing = handlers.get(name) ?? [];
|
|
5
|
+
existing.push(handler);
|
|
6
|
+
handlers.set(name, existing);
|
|
7
|
+
}
|
|
8
|
+
export function emitAutopilotEvent(event) {
|
|
9
|
+
// Fire-and-forget: never throw, never await
|
|
10
|
+
const eventHandlers = handlers.get(event.name) ?? [];
|
|
11
|
+
for (const handler of eventHandlers) {
|
|
12
|
+
// Execute each handler in its own micro-task to avoid blocking
|
|
13
|
+
Promise.resolve()
|
|
14
|
+
.then(() => {
|
|
15
|
+
handler(event);
|
|
16
|
+
})
|
|
17
|
+
.catch((err) => {
|
|
18
|
+
// Silent: autopilot errors never surface to user
|
|
19
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
20
|
+
console.error(`[autopilot] handler error for ${event.name}: ${message}`);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** Clears all handlers — used in tests */
|
|
25
|
+
export function clearAutopilotHandlers() {
|
|
26
|
+
handlers.clear();
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=event-bus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../../src/engine/autopilot/event-bus.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAO9F,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAsC,CAAC;AAE/D,MAAM,UAAU,gBAAgB,CAAC,IAAwB,EAAE,OAAqB;IAC9E,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC1C,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAqB;IACtD,4CAA4C;IAC5C,MAAM,aAAa,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACrD,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;QACpC,+DAA+D;QAC/D,OAAO,CAAC,OAAO,EAAE;aACd,IAAI,CAAC,GAAG,EAAE;YACT,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YACtB,iDAAiD;YACjD,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,CAAC,KAAK,CAAC,iCAAiC,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;QAC3E,CAAC,CAAC,CAAC;IACP,CAAC;AACH,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,sBAAsB;IACpC,QAAQ,CAAC,KAAK,EAAE,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trigger-rules.d.ts","sourceRoot":"","sources":["../../../src/engine/autopilot/trigger-rules.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,eAAO,MAAM,qBAAqB,EAAE,WAAW,EA0H9C,CAAC"}
|