aidp 0.17.1 → 0.18.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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +69 -0
  3. data/lib/aidp/cli.rb +43 -2
  4. data/lib/aidp/config.rb +9 -14
  5. data/lib/aidp/execute/prompt_manager.rb +128 -1
  6. data/lib/aidp/execute/repl_macros.rb +555 -0
  7. data/lib/aidp/execute/work_loop_runner.rb +108 -1
  8. data/lib/aidp/harness/ai_decision_engine.rb +376 -0
  9. data/lib/aidp/harness/capability_registry.rb +273 -0
  10. data/lib/aidp/harness/config_schema.rb +305 -1
  11. data/lib/aidp/harness/configuration.rb +452 -0
  12. data/lib/aidp/harness/enhanced_runner.rb +7 -1
  13. data/lib/aidp/harness/provider_factory.rb +0 -2
  14. data/lib/aidp/harness/runner.rb +7 -1
  15. data/lib/aidp/harness/thinking_depth_manager.rb +335 -0
  16. data/lib/aidp/harness/zfc_condition_detector.rb +395 -0
  17. data/lib/aidp/init/devcontainer_generator.rb +274 -0
  18. data/lib/aidp/init/runner.rb +37 -10
  19. data/lib/aidp/init.rb +1 -0
  20. data/lib/aidp/prompt_optimization/context_composer.rb +286 -0
  21. data/lib/aidp/prompt_optimization/optimizer.rb +335 -0
  22. data/lib/aidp/prompt_optimization/prompt_builder.rb +309 -0
  23. data/lib/aidp/prompt_optimization/relevance_scorer.rb +256 -0
  24. data/lib/aidp/prompt_optimization/source_code_fragmenter.rb +308 -0
  25. data/lib/aidp/prompt_optimization/style_guide_indexer.rb +240 -0
  26. data/lib/aidp/prompt_optimization/template_indexer.rb +250 -0
  27. data/lib/aidp/provider_manager.rb +0 -2
  28. data/lib/aidp/providers/anthropic.rb +19 -0
  29. data/lib/aidp/setup/wizard.rb +299 -4
  30. data/lib/aidp/utils/devcontainer_detector.rb +166 -0
  31. data/lib/aidp/version.rb +1 -1
  32. data/lib/aidp/watch/build_processor.rb +72 -6
  33. data/lib/aidp/watch/repository_client.rb +2 -1
  34. data/lib/aidp.rb +0 -1
  35. data/templates/aidp.yml.example +128 -0
  36. metadata +14 -2
  37. data/lib/aidp/providers/macos_ui.rb +0 -102
@@ -275,6 +275,24 @@ module Aidp
275
275
  usage: "/skill <list|show|use> [args]",
276
276
  example: "/skill list",
277
277
  handler: method(:cmd_skill)
278
+ },
279
+ "/tools" => {
280
+ description: "Manage available tools (coverage, testing, etc.)",
281
+ usage: "/tools <show|coverage|test> [subcommand]",
282
+ example: "/tools show",
283
+ handler: method(:cmd_tools)
284
+ },
285
+ "/thinking" => {
286
+ description: "Manage thinking depth tier for model selection",
287
+ usage: "/thinking <show|set|max|reset> [tier]",
288
+ example: "/thinking show",
289
+ handler: method(:cmd_thinking)
290
+ },
291
+ "/prompt" => {
292
+ description: "Inspect and control prompt optimization",
293
+ usage: "/prompt <explain|stats|expand|reset>",
294
+ example: "/prompt explain",
295
+ handler: method(:cmd_prompt)
278
296
  }
279
297
  }
280
298
  end
@@ -1489,6 +1507,543 @@ module Aidp
1489
1507
  }
1490
1508
  end
1491
1509
  end
1510
+
1511
+ # /tools command - manage available tools
1512
+ def cmd_tools(args)
1513
+ Aidp.log_debug("repl_macros", "Executing /tools command", args: args)
1514
+
1515
+ subcommand = args[0]&.downcase
1516
+
1517
+ case subcommand
1518
+ when "show"
1519
+ cmd_tools_show
1520
+ when "coverage"
1521
+ cmd_tools_coverage(args[1..])
1522
+ when "test"
1523
+ cmd_tools_test(args[1..])
1524
+ else
1525
+ {
1526
+ success: false,
1527
+ message: "Usage: /tools <command> [args]\n\nCommands:\n show - Show configured tools and their status\n coverage - Run coverage analysis and show delta\n test <type> - Run interactive tests (web, cli, desktop)\n\nExamples:\n /tools show\n /tools coverage\n /tools test web",
1528
+ action: :none
1529
+ }
1530
+ end
1531
+ end
1532
+
1533
+ def cmd_tools_show
1534
+ require_relative "../harness/configuration"
1535
+
1536
+ begin
1537
+ config = Aidp::Harness::Configuration.new(@project_dir)
1538
+
1539
+ output = ["šŸ“Š Configured Tools\n", "=" * 50]
1540
+
1541
+ # Coverage tools
1542
+ if config.coverage_enabled?
1543
+ output << "\nšŸ” Coverage:"
1544
+ output << " Tool: #{config.coverage_tool || "not specified"}"
1545
+ output << " Command: #{config.coverage_run_command || "not specified"}"
1546
+ output << " Report paths: #{config.coverage_report_paths.join(", ")}" if config.coverage_report_paths.any?
1547
+ output << " Fail on drop: #{config.coverage_fail_on_drop? ? "yes" : "no"}"
1548
+ output << " Minimum coverage: #{config.coverage_minimum || "not set"}%" if config.coverage_minimum
1549
+ else
1550
+ output << "\nšŸ” Coverage: disabled"
1551
+ end
1552
+
1553
+ # VCS configuration
1554
+ output << "\n\nšŸ—‚ļø Version Control:"
1555
+ output << " Tool: #{config.vcs_tool}"
1556
+ output << " Behavior: #{config.vcs_behavior}"
1557
+ output << " Conventional commits: #{config.conventional_commits? ? "yes" : "no"}"
1558
+
1559
+ # Interactive testing
1560
+ if config.interactive_testing_enabled?
1561
+ output << "\n\nšŸŽÆ Interactive Testing:"
1562
+ output << " App type: #{config.interactive_testing_app_type}"
1563
+ tools = config.interactive_testing_tools
1564
+ if tools.any?
1565
+ tools.each do |category, category_tools|
1566
+ output << " #{category.to_s.capitalize}:"
1567
+ category_tools.each do |tool_name, tool_config|
1568
+ next unless tool_config[:enabled]
1569
+ output << " • #{tool_name}: enabled"
1570
+ output << " Run: #{tool_config[:run]}" if tool_config[:run]
1571
+ output << " Specs: #{tool_config[:specs_dir]}" if tool_config[:specs_dir]
1572
+ end
1573
+ end
1574
+ else
1575
+ output << " No tools configured"
1576
+ end
1577
+ else
1578
+ output << "\n\nšŸŽÆ Interactive Testing: disabled"
1579
+ end
1580
+
1581
+ # Model families
1582
+ output << "\n\nšŸ¤– Model Families:"
1583
+ config.configured_providers.each do |provider|
1584
+ family = config.model_family(provider)
1585
+ output << " #{provider}: #{family}"
1586
+ end
1587
+
1588
+ {
1589
+ success: true,
1590
+ message: output.join("\n"),
1591
+ action: :none
1592
+ }
1593
+ rescue => e
1594
+ Aidp.log_error("repl_macros", "Failed to show tools", error: e.message)
1595
+ {
1596
+ success: false,
1597
+ message: "Failed to load tool configuration: #{e.message}",
1598
+ action: :none
1599
+ }
1600
+ end
1601
+ end
1602
+
1603
+ def cmd_tools_coverage(args)
1604
+ require_relative "../harness/configuration"
1605
+
1606
+ begin
1607
+ config = Aidp::Harness::Configuration.new(@project_dir)
1608
+
1609
+ unless config.coverage_enabled?
1610
+ return {
1611
+ success: false,
1612
+ message: "Coverage is not enabled. Run 'aidp config --interactive' to configure coverage.",
1613
+ action: :none
1614
+ }
1615
+ end
1616
+
1617
+ unless config.coverage_run_command
1618
+ return {
1619
+ success: false,
1620
+ message: "Coverage run command not configured. Run 'aidp config --interactive' to set it up.",
1621
+ action: :none
1622
+ }
1623
+ end
1624
+
1625
+ Aidp.log_debug("repl_macros", "Running coverage", command: config.coverage_run_command)
1626
+
1627
+ {
1628
+ success: true,
1629
+ message: "Running coverage with: #{config.coverage_run_command}\n(Coverage execution to be implemented in work loop)",
1630
+ action: :run_coverage,
1631
+ data: {
1632
+ command: config.coverage_run_command,
1633
+ tool: config.coverage_tool,
1634
+ report_paths: config.coverage_report_paths
1635
+ }
1636
+ }
1637
+ rescue => e
1638
+ Aidp.log_error("repl_macros", "Failed to run coverage", error: e.message)
1639
+ {
1640
+ success: false,
1641
+ message: "Failed to run coverage: #{e.message}",
1642
+ action: :none
1643
+ }
1644
+ end
1645
+ end
1646
+
1647
+ def cmd_tools_test(args)
1648
+ require_relative "../harness/configuration"
1649
+
1650
+ test_type = args[0]&.downcase
1651
+
1652
+ begin
1653
+ config = Aidp::Harness::Configuration.new(@project_dir)
1654
+
1655
+ unless config.interactive_testing_enabled?
1656
+ return {
1657
+ success: false,
1658
+ message: "Interactive testing is not enabled. Run 'aidp config --interactive' to configure it.",
1659
+ action: :none
1660
+ }
1661
+ end
1662
+
1663
+ unless test_type
1664
+ return {
1665
+ success: false,
1666
+ message: "Usage: /tools test <type>\n\nTypes: web, cli, desktop\n\nExample: /tools test web",
1667
+ action: :none
1668
+ }
1669
+ end
1670
+
1671
+ unless %w[web cli desktop].include?(test_type)
1672
+ return {
1673
+ success: false,
1674
+ message: "Invalid test type: #{test_type}. Must be one of: web, cli, desktop",
1675
+ action: :none
1676
+ }
1677
+ end
1678
+
1679
+ tools = config.interactive_testing_tools.dig(test_type.to_sym)
1680
+ unless tools&.any? { |_, t| t[:enabled] }
1681
+ return {
1682
+ success: false,
1683
+ message: "No #{test_type} testing tools configured. Run 'aidp config --interactive' to set them up.",
1684
+ action: :none
1685
+ }
1686
+ end
1687
+
1688
+ enabled_tools = tools.select { |_, t| t[:enabled] }
1689
+ tool_list = enabled_tools.map { |name, cfg| " • #{name}: #{cfg[:run] || "no command"}" }.join("\n")
1690
+
1691
+ Aidp.log_debug("repl_macros", "Running interactive tests", type: test_type, tools: enabled_tools.keys)
1692
+
1693
+ {
1694
+ success: true,
1695
+ message: "Running #{test_type} tests:\n#{tool_list}\n(Test execution to be implemented in work loop)",
1696
+ action: :run_interactive_tests,
1697
+ data: {
1698
+ test_type: test_type,
1699
+ tools: enabled_tools
1700
+ }
1701
+ }
1702
+ rescue => e
1703
+ Aidp.log_error("repl_macros", "Failed to run interactive tests", error: e.message)
1704
+ {
1705
+ success: false,
1706
+ message: "Failed to run interactive tests: #{e.message}",
1707
+ action: :none
1708
+ }
1709
+ end
1710
+ end
1711
+
1712
+ # Command: /thinking
1713
+ def cmd_thinking(args)
1714
+ subcommand = args[0]
1715
+
1716
+ case subcommand
1717
+ when "show"
1718
+ cmd_thinking_show
1719
+ when "set"
1720
+ cmd_thinking_set(args[1])
1721
+ when "max"
1722
+ cmd_thinking_max(args[1])
1723
+ when "reset"
1724
+ cmd_thinking_reset
1725
+ else
1726
+ {
1727
+ success: false,
1728
+ message: "Unknown subcommand: #{subcommand}\nUsage: /thinking <show|set|max|reset> [tier]",
1729
+ action: :none
1730
+ }
1731
+ end
1732
+ rescue => e
1733
+ Aidp.log_error("repl_macros", "Failed to execute thinking command", error: e.message)
1734
+ {
1735
+ success: false,
1736
+ message: "Failed to execute thinking command: #{e.message}",
1737
+ action: :none
1738
+ }
1739
+ end
1740
+
1741
+ # Subcommand: /thinking show
1742
+ def cmd_thinking_show
1743
+ require_relative "../harness/configuration"
1744
+ require_relative "../harness/thinking_depth_manager"
1745
+
1746
+ config = Aidp::Harness::Configuration.new(@project_dir)
1747
+ manager = Aidp::Harness::ThinkingDepthManager.new(config, root_dir: @project_dir)
1748
+
1749
+ lines = []
1750
+ lines << "Thinking Depth Configuration:"
1751
+ lines << ""
1752
+ lines << "Current Tier: #{manager.current_tier}"
1753
+ lines << "Default Tier: #{manager.default_tier}"
1754
+ lines << "Max Tier: #{manager.max_tier}"
1755
+ lines << ""
1756
+
1757
+ # Show all available tiers
1758
+ require_relative "../harness/capability_registry"
1759
+ lines << "Available Tiers:"
1760
+ Aidp::Harness::CapabilityRegistry::VALID_TIERS.each do |tier|
1761
+ marker = if tier == manager.current_tier
1762
+ "→"
1763
+ elsif tier == manager.max_tier
1764
+ "↑"
1765
+ else
1766
+ " "
1767
+ end
1768
+ lines << " #{marker} #{tier}"
1769
+ end
1770
+ lines << ""
1771
+ lines << "Legend: → current, ↑ max allowed"
1772
+ lines << ""
1773
+
1774
+ # Show current model selection
1775
+ current_model = manager.select_model_for_tier
1776
+ if current_model
1777
+ provider, model_name, model_data = current_model
1778
+ lines << "Current Model: #{provider}/#{model_name}"
1779
+ lines << " Tier: #{model_data["tier"]}" if model_data["tier"]
1780
+ lines << " Context Window: #{model_data["context_window"]}" if model_data["context_window"]
1781
+ else
1782
+ lines << "Current Model: (none selected)"
1783
+ end
1784
+
1785
+ lines << ""
1786
+ lines << "Provider Switching: #{config.allow_provider_switch_for_tier? ? "enabled" : "disabled"}"
1787
+
1788
+ # Show escalation config
1789
+ escalation = config.escalation_config
1790
+ lines << ""
1791
+ lines << "Escalation Settings:"
1792
+ lines << " Fail Attempts Threshold: #{escalation[:on_fail_attempts]}"
1793
+ if escalation[:on_complexity_threshold]&.any?
1794
+ lines << " Complexity Thresholds:"
1795
+ escalation[:on_complexity_threshold].each do |key, value|
1796
+ lines << " #{key}: #{value}"
1797
+ end
1798
+ end
1799
+
1800
+ {
1801
+ success: true,
1802
+ message: lines.join("\n"),
1803
+ action: :display
1804
+ }
1805
+ end
1806
+
1807
+ # Subcommand: /thinking set <tier>
1808
+ def cmd_thinking_set(tier)
1809
+ unless tier
1810
+ return {
1811
+ success: false,
1812
+ message: "Usage: /thinking set <tier>\nTiers: mini, standard, thinking, pro, max",
1813
+ action: :none
1814
+ }
1815
+ end
1816
+
1817
+ require_relative "../harness/configuration"
1818
+ require_relative "../harness/thinking_depth_manager"
1819
+
1820
+ config = Aidp::Harness::Configuration.new(@project_dir)
1821
+ manager = Aidp::Harness::ThinkingDepthManager.new(config, root_dir: @project_dir)
1822
+
1823
+ old_tier = manager.current_tier
1824
+ manager.current_tier = tier
1825
+
1826
+ {
1827
+ success: true,
1828
+ message: "Thinking tier changed: #{old_tier} → #{tier}\nMax tier: #{manager.max_tier}",
1829
+ action: :tier_changed
1830
+ }
1831
+ rescue ArgumentError => e
1832
+ {
1833
+ success: false,
1834
+ message: "Invalid tier: #{e.message}\nValid tiers: mini, standard, thinking, pro, max",
1835
+ action: :none
1836
+ }
1837
+ end
1838
+
1839
+ # Subcommand: /thinking max <tier>
1840
+ def cmd_thinking_max(tier)
1841
+ unless tier
1842
+ return {
1843
+ success: false,
1844
+ message: "Usage: /thinking max <tier>\nTiers: mini, standard, thinking, pro, max",
1845
+ action: :none
1846
+ }
1847
+ end
1848
+
1849
+ require_relative "../harness/configuration"
1850
+ require_relative "../harness/thinking_depth_manager"
1851
+
1852
+ config = Aidp::Harness::Configuration.new(@project_dir)
1853
+ manager = Aidp::Harness::ThinkingDepthManager.new(config, root_dir: @project_dir)
1854
+
1855
+ old_max = manager.max_tier
1856
+ manager.max_tier = tier
1857
+
1858
+ {
1859
+ success: true,
1860
+ message: "Max tier changed: #{old_max} → #{tier}\nCurrent tier: #{manager.current_tier}",
1861
+ action: :max_tier_changed
1862
+ }
1863
+ rescue ArgumentError => e
1864
+ {
1865
+ success: false,
1866
+ message: "Invalid tier: #{e.message}\nValid tiers: mini, standard, thinking, pro, max",
1867
+ action: :none
1868
+ }
1869
+ end
1870
+
1871
+ # Subcommand: /thinking reset
1872
+ def cmd_thinking_reset
1873
+ require_relative "../harness/configuration"
1874
+ require_relative "../harness/thinking_depth_manager"
1875
+
1876
+ config = Aidp::Harness::Configuration.new(@project_dir)
1877
+ manager = Aidp::Harness::ThinkingDepthManager.new(config, root_dir: @project_dir)
1878
+
1879
+ old_tier = manager.current_tier
1880
+ manager.reset_to_default
1881
+
1882
+ {
1883
+ success: true,
1884
+ message: "Thinking tier reset: #{old_tier} → #{manager.current_tier}\nEscalation count cleared",
1885
+ action: :tier_reset
1886
+ }
1887
+ end
1888
+
1889
+ # Command: /prompt - Inspect and control prompt optimization
1890
+ def cmd_prompt(args)
1891
+ subcommand = args[0]
1892
+
1893
+ case subcommand
1894
+ when "explain"
1895
+ cmd_prompt_explain
1896
+ when "stats"
1897
+ cmd_prompt_stats
1898
+ when "expand"
1899
+ cmd_prompt_expand(args[1])
1900
+ when "reset"
1901
+ cmd_prompt_reset
1902
+ else
1903
+ {
1904
+ success: false,
1905
+ message: "Unknown subcommand: #{subcommand}\nUsage: /prompt <explain|stats|expand|reset>",
1906
+ action: :none
1907
+ }
1908
+ end
1909
+ rescue => e
1910
+ Aidp.log_error("repl_macros", "Failed to execute prompt command", error: e.message)
1911
+ {
1912
+ success: false,
1913
+ message: "Failed to execute prompt command: #{e.message}",
1914
+ action: :none
1915
+ }
1916
+ end
1917
+
1918
+ # Subcommand: /prompt explain
1919
+ # Shows which fragments were selected for the current prompt and why
1920
+ def cmd_prompt_explain
1921
+ require_relative "prompt_manager"
1922
+
1923
+ prompt_manager = PromptManager.new(@project_dir, config: load_config)
1924
+
1925
+ unless prompt_manager.optimization_enabled?
1926
+ return {
1927
+ success: false,
1928
+ message: "Prompt optimization is not enabled. Check your .aidp/config.yml:\n" \
1929
+ "prompt_optimization:\n enabled: true",
1930
+ action: :none
1931
+ }
1932
+ end
1933
+
1934
+ unless prompt_manager.last_optimization_stats
1935
+ return {
1936
+ success: false,
1937
+ message: "No optimization performed yet. Prompt optimization will be used on the next work loop iteration.",
1938
+ action: :none
1939
+ }
1940
+ end
1941
+
1942
+ report = prompt_manager.optimization_report
1943
+ {
1944
+ success: true,
1945
+ message: report,
1946
+ action: :show_optimization_report
1947
+ }
1948
+ end
1949
+
1950
+ # Subcommand: /prompt stats
1951
+ # Shows overall optimizer statistics across all runs
1952
+ def cmd_prompt_stats
1953
+ require_relative "prompt_manager"
1954
+
1955
+ prompt_manager = PromptManager.new(@project_dir, config: load_config)
1956
+
1957
+ unless prompt_manager.optimization_enabled?
1958
+ return {
1959
+ success: false,
1960
+ message: "Prompt optimization is not enabled.",
1961
+ action: :none
1962
+ }
1963
+ end
1964
+
1965
+ stats = prompt_manager.optimizer_stats
1966
+ unless stats
1967
+ return {
1968
+ success: false,
1969
+ message: "No optimization statistics available.",
1970
+ action: :none
1971
+ }
1972
+ end
1973
+
1974
+ lines = []
1975
+ lines << "# Prompt Optimizer Statistics"
1976
+ lines << ""
1977
+ lines << "- **Total Runs**: #{stats[:runs_count]}"
1978
+ lines << "- **Total Fragments Indexed**: #{stats[:total_fragments_indexed]}"
1979
+ lines << "- **Total Fragments Selected**: #{stats[:total_fragments_selected]}"
1980
+ lines << "- **Total Fragments Excluded**: #{stats[:total_fragments_excluded]}"
1981
+ lines << "- **Total Tokens Used**: #{stats[:total_tokens_used]}"
1982
+ lines << "- **Average Fragments/Run**: #{stats[:average_fragments_selected]}"
1983
+ lines << "- **Average Budget Utilization**: #{stats[:average_budget_utilization]}%"
1984
+ lines << "- **Average Optimization Time**: #{stats[:average_optimization_time_ms]}ms"
1985
+
1986
+ {
1987
+ success: true,
1988
+ message: lines.join("\n"),
1989
+ action: :show_optimizer_stats
1990
+ }
1991
+ end
1992
+
1993
+ # Subcommand: /prompt expand <fragment_id>
1994
+ # Adds a specific omitted fragment to the next prompt
1995
+ def cmd_prompt_expand(fragment_id)
1996
+ unless fragment_id
1997
+ return {
1998
+ success: false,
1999
+ message: "Usage: /prompt expand <fragment_id>\nUse /prompt explain to see available fragments",
2000
+ action: :none
2001
+ }
2002
+ end
2003
+
2004
+ # For now, this is a placeholder - full implementation would:
2005
+ # 1. Look up the fragment by ID
2006
+ # 2. Add it to an override list
2007
+ # 3. Include it in the next prompt generation
2008
+ {
2009
+ success: true,
2010
+ message: "Fragment expansion not yet implemented.\n" \
2011
+ "This will be available in a future update to manually include excluded fragments.",
2012
+ action: :feature_not_implemented
2013
+ }
2014
+ end
2015
+
2016
+ # Subcommand: /prompt reset
2017
+ # Clears optimizer cache and resets to default behavior
2018
+ def cmd_prompt_reset
2019
+ require_relative "prompt_manager"
2020
+
2021
+ prompt_manager = PromptManager.new(@project_dir, config: load_config)
2022
+
2023
+ unless prompt_manager.optimization_enabled?
2024
+ return {
2025
+ success: false,
2026
+ message: "Prompt optimization is not enabled.",
2027
+ action: :none
2028
+ }
2029
+ end
2030
+
2031
+ prompt_manager.optimizer.clear_cache
2032
+
2033
+ {
2034
+ success: true,
2035
+ message: "Optimizer cache cleared. Next prompt will use fresh indexing.",
2036
+ action: :optimizer_reset
2037
+ }
2038
+ end
2039
+
2040
+ private
2041
+
2042
+ # Load configuration for prompt commands
2043
+ def load_config
2044
+ require_relative "../harness/configuration"
2045
+ Aidp::Harness::Configuration.new(@project_dir)
2046
+ end
1492
2047
  end
1493
2048
  end
1494
2049
  end
@@ -46,7 +46,7 @@ module Aidp
46
46
  @project_dir = project_dir
47
47
  @provider_manager = provider_manager
48
48
  @config = config
49
- @prompt_manager = PromptManager.new(project_dir)
49
+ @prompt_manager = PromptManager.new(project_dir, config: config)
50
50
  @test_runner = Aidp::Harness::TestRunner.new(project_dir, config)
51
51
  @checkpoint = Checkpoint.new(project_dir)
52
52
  @checkpoint_display = CheckpointDisplay.new
@@ -343,6 +343,16 @@ module Aidp
343
343
 
344
344
  # Create initial PROMPT.md with all context
345
345
  def create_initial_prompt(step_spec, context)
346
+ # Try intelligent prompt optimization first (ZFC-powered)
347
+ if @prompt_manager.optimization_enabled?
348
+ if create_optimized_prompt(step_spec, context)
349
+ return
350
+ end
351
+ # Fallback to traditional prompt on optimization failure
352
+ display_message(" āš ļø Prompt optimization failed, using traditional approach", type: :warning)
353
+ end
354
+
355
+ # Traditional prompt building (fallback or when optimization disabled)
346
356
  template_content = load_template(step_spec["templates"]&.first)
347
357
  prd_content = load_prd
348
358
  style_guide = load_style_guide
@@ -364,6 +374,103 @@ module Aidp
364
374
  display_message(" Created PROMPT.md (#{initial_prompt.length} chars)", type: :info)
365
375
  end
366
376
 
377
+ # Create prompt using intelligent optimization (Zero Framework Cognition)
378
+ # Selects only the most relevant fragments from style guide, templates, and code
379
+ def create_optimized_prompt(step_spec, context)
380
+ user_input = format_user_input(context[:user_input])
381
+
382
+ # Infer task type from step name
383
+ task_type = infer_task_type(step_spec, user_input)
384
+
385
+ # Extract affected files from context or PRD
386
+ affected_files = extract_affected_files(context, user_input)
387
+
388
+ # Build task context for optimizer
389
+ task_context = {
390
+ task_type: task_type,
391
+ description: build_task_description(user_input, context),
392
+ affected_files: affected_files,
393
+ step_name: @step_name,
394
+ tags: extract_tags(user_input, step_spec)
395
+ }
396
+
397
+ # Use optimizer to create prompt
398
+ success = @prompt_manager.write_optimized(
399
+ task_context,
400
+ include_metadata: @config.prompt_log_fragments?
401
+ )
402
+
403
+ if success
404
+ stats = @prompt_manager.last_optimization_stats
405
+ display_message(" ✨ Created optimized PROMPT.md", type: :success)
406
+ display_message(" Selected: #{stats.selected_count} fragments, Excluded: #{stats.excluded_count}", type: :info)
407
+ display_message(" Tokens: #{stats.total_tokens} (#{stats.budget_utilization.round(1)}% of budget)", type: :info)
408
+ display_message(" Avg relevance: #{(stats.average_score * 100).round(1)}%", type: :info)
409
+ end
410
+
411
+ success
412
+ end
413
+
414
+ # Infer task type from step name and context
415
+ def infer_task_type(step_spec, user_input)
416
+ step_name = @step_name.to_s.downcase
417
+ input_lower = user_input.to_s.downcase
418
+
419
+ return :test if step_name.include?("test") || input_lower.include?("test")
420
+ return :bugfix if step_name.include?("fix") || input_lower.include?("fix") || input_lower.include?("bug")
421
+ return :refactor if step_name.include?("refactor") || input_lower.include?("refactor")
422
+ return :analysis if step_name.include?("analyz") || step_name.include?("review")
423
+
424
+ :feature # Default to feature
425
+ end
426
+
427
+ # Extract files that will be affected by this work
428
+ def extract_affected_files(context, user_input)
429
+ files = []
430
+
431
+ # From user input (e.g., "update lib/user.rb")
432
+ user_input&.scan(/[\w\/]+\.rb/)&.each do |file|
433
+ files << file
434
+ end
435
+
436
+ # From deterministic outputs
437
+ context[:deterministic_outputs]&.each do |output|
438
+ if output[:output_path]&.end_with?(".rb")
439
+ files << output[:output_path]
440
+ end
441
+ end
442
+
443
+ files.uniq
444
+ end
445
+
446
+ # Build task description from context
447
+ def build_task_description(user_input, context)
448
+ parts = []
449
+ parts << user_input if user_input && !user_input.empty?
450
+ parts << context[:previous_agent_summary] if context[:previous_agent_summary]
451
+ parts.join("\n\n")
452
+ end
453
+
454
+ # Extract relevant tags from input and spec
455
+ def extract_tags(user_input, step_spec)
456
+ tags = []
457
+ input_lower = user_input.to_s.downcase
458
+
459
+ # Common tags from content
460
+ tags << "testing" if input_lower.include?("test")
461
+ tags << "security" if input_lower.include?("security") || input_lower.include?("auth")
462
+ tags << "api" if input_lower.include?("api") || input_lower.include?("endpoint")
463
+ tags << "database" if input_lower.include?("database") || input_lower.include?("migration")
464
+ tags << "performance" if input_lower.include?("performance") || input_lower.include?("optim")
465
+
466
+ # Tags from step spec
467
+ if step_spec["tags"]
468
+ tags.concat(Array(step_spec["tags"]))
469
+ end
470
+
471
+ tags.uniq
472
+ end
473
+
367
474
  def build_initial_prompt_content(template:, prd:, style_guide:, user_input:, step_name:, deterministic_outputs:, previous_agent_summary:)
368
475
  parts = []
369
476