empathy-framework 3.5.6__py3-none-any.whl → 3.7.0__py3-none-any.whl

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 (72) hide show
  1. agents/compliance_anticipation_agent.py +113 -118
  2. agents/compliance_db.py +339 -0
  3. agents/epic_integration_wizard.py +37 -48
  4. agents/notifications.py +291 -0
  5. agents/trust_building_behaviors.py +66 -85
  6. coach_wizards/__init__.py +11 -12
  7. coach_wizards/accessibility_wizard.py +12 -12
  8. coach_wizards/api_wizard.py +12 -12
  9. coach_wizards/base_wizard.py +26 -20
  10. coach_wizards/cicd_wizard.py +15 -13
  11. coach_wizards/compliance_wizard.py +12 -12
  12. coach_wizards/database_wizard.py +12 -12
  13. coach_wizards/debugging_wizard.py +12 -12
  14. coach_wizards/documentation_wizard.py +12 -12
  15. coach_wizards/generate_wizards.py +1 -2
  16. coach_wizards/localization_wizard.py +21 -14
  17. coach_wizards/migration_wizard.py +12 -12
  18. coach_wizards/monitoring_wizard.py +12 -12
  19. coach_wizards/observability_wizard.py +12 -12
  20. coach_wizards/performance_wizard.py +12 -12
  21. coach_wizards/prompt_engineering_wizard.py +22 -25
  22. coach_wizards/refactoring_wizard.py +12 -12
  23. coach_wizards/scaling_wizard.py +12 -12
  24. coach_wizards/security_wizard.py +12 -12
  25. coach_wizards/testing_wizard.py +12 -12
  26. {empathy_framework-3.5.6.dist-info → empathy_framework-3.7.0.dist-info}/METADATA +234 -30
  27. empathy_framework-3.7.0.dist-info/RECORD +105 -0
  28. empathy_healthcare_plugin/__init__.py +1 -2
  29. empathy_llm_toolkit/__init__.py +5 -6
  30. empathy_llm_toolkit/claude_memory.py +14 -15
  31. empathy_llm_toolkit/code_health.py +27 -19
  32. empathy_llm_toolkit/contextual_patterns.py +11 -12
  33. empathy_llm_toolkit/core.py +43 -49
  34. empathy_llm_toolkit/git_pattern_extractor.py +16 -12
  35. empathy_llm_toolkit/levels.py +6 -13
  36. empathy_llm_toolkit/pattern_confidence.py +14 -18
  37. empathy_llm_toolkit/pattern_resolver.py +10 -12
  38. empathy_llm_toolkit/pattern_summary.py +13 -11
  39. empathy_llm_toolkit/providers.py +27 -38
  40. empathy_llm_toolkit/session_status.py +18 -20
  41. empathy_llm_toolkit/state.py +20 -21
  42. empathy_os/__init__.py +72 -73
  43. empathy_os/cli.py +193 -98
  44. empathy_os/cli_unified.py +68 -41
  45. empathy_os/config.py +31 -31
  46. empathy_os/coordination.py +48 -54
  47. empathy_os/core.py +90 -99
  48. empathy_os/cost_tracker.py +20 -23
  49. empathy_os/discovery.py +9 -11
  50. empathy_os/emergence.py +20 -21
  51. empathy_os/exceptions.py +18 -30
  52. empathy_os/feedback_loops.py +27 -30
  53. empathy_os/levels.py +31 -34
  54. empathy_os/leverage_points.py +27 -28
  55. empathy_os/logging_config.py +11 -12
  56. empathy_os/monitoring.py +27 -27
  57. empathy_os/pattern_library.py +29 -28
  58. empathy_os/persistence.py +30 -34
  59. empathy_os/platform_utils.py +46 -47
  60. empathy_os/redis_config.py +14 -15
  61. empathy_os/redis_memory.py +53 -56
  62. empathy_os/templates.py +12 -11
  63. empathy_os/trust_building.py +44 -36
  64. empathy_os/workflow_commands.py +123 -31
  65. empathy_software_plugin/__init__.py +1 -2
  66. empathy_software_plugin/cli.py +32 -25
  67. empathy_software_plugin/plugin.py +4 -8
  68. empathy_framework-3.5.6.dist-info/RECORD +0 -103
  69. {empathy_framework-3.5.6.dist-info → empathy_framework-3.7.0.dist-info}/WHEEL +0 -0
  70. {empathy_framework-3.5.6.dist-info → empathy_framework-3.7.0.dist-info}/entry_points.txt +0 -0
  71. {empathy_framework-3.5.6.dist-info → empathy_framework-3.7.0.dist-info}/licenses/LICENSE +0 -0
  72. {empathy_framework-3.5.6.dist-info → empathy_framework-3.7.0.dist-info}/top_level.txt +0 -0
empathy_os/cli.py CHANGED
@@ -1,5 +1,4 @@
1
- """
2
- Command-Line Interface for Empathy Framework
1
+ """Command-Line Interface for Empathy Framework
3
2
 
4
3
  Provides CLI commands for:
5
4
  - Running interactive REPL (empathy run)
@@ -482,10 +481,9 @@ for a quick reference of all commands.
482
481
  print(" Congratulations! You've completed the onboarding!")
483
482
  print()
484
483
  _show_achievements(engine)
485
- else:
486
- if step_data["action"]:
487
- print(f" NEXT: Run '{step_data['action']}'")
488
- print(" Then run 'empathy onboard' to continue")
484
+ elif step_data["action"]:
485
+ print(f" NEXT: Run '{step_data['action']}'")
486
+ print(" Then run 'empathy onboard' to continue")
489
487
 
490
488
  print()
491
489
  print("-" * 60)
@@ -783,7 +781,7 @@ def cmd_patterns_resolve(args):
783
781
  if not args.root_cause or not args.fix:
784
782
  print("✗ --root-cause and --fix are required when resolving a bug")
785
783
  print(
786
- " Example: empathy patterns resolve bug_123 --root-cause 'Null check' --fix 'Added ?.'"
784
+ " Example: empathy patterns resolve bug_123 --root-cause 'Null check' --fix 'Added ?.'",
787
785
  )
788
786
  sys.exit(1)
789
787
 
@@ -870,8 +868,8 @@ def cmd_review(args):
870
868
  "files": args.files,
871
869
  "staged_only": args.staged,
872
870
  "severity_threshold": args.severity,
873
- }
874
- )
871
+ },
872
+ ),
875
873
  )
876
874
 
877
875
  # Output results
@@ -972,7 +970,7 @@ def cmd_health(args):
972
970
  print(f"\n⚠ Skipped {len(result['skipped'])} issue(s) (could not auto-fix)")
973
971
  else:
974
972
  print(
975
- f"\n⚠ Skipped {len(result['skipped'])} issue(s) (use --interactive to review)"
973
+ f"\n⚠ Skipped {len(result['skipped'])} issue(s) (use --interactive to review)",
976
974
  )
977
975
 
978
976
  if result["failed"]:
@@ -1528,7 +1526,7 @@ def cmd_provider_show(args):
1528
1526
  # Detect available providers
1529
1527
  config = ProviderConfig.auto_detect()
1530
1528
  print(
1531
- f"\nDetected API keys for: {', '.join(config.available_providers) if config.available_providers else 'None'}"
1529
+ f"\nDetected API keys for: {', '.join(config.available_providers) if config.available_providers else 'None'}",
1532
1530
  )
1533
1531
 
1534
1532
  # Load workflow config
@@ -1665,7 +1663,7 @@ def _generate_claude_rule(category: str, patterns: list) -> str:
1665
1663
  "",
1666
1664
  "When debugging similar issues, consider these historical fixes:",
1667
1665
  "",
1668
- ]
1666
+ ],
1669
1667
  )
1670
1668
  for p in patterns[:20]: # Limit to 20 most recent
1671
1669
  bug_type = p.get("bug_type", "unknown")
@@ -1687,7 +1685,7 @@ def _generate_claude_rule(category: str, patterns: list) -> str:
1687
1685
  "",
1688
1686
  "Previously reviewed security items:",
1689
1687
  "",
1690
- ]
1688
+ ],
1691
1689
  )
1692
1690
  for p in patterns[:20]:
1693
1691
  decision = p.get("decision", "unknown")
@@ -1704,7 +1702,7 @@ def _generate_claude_rule(category: str, patterns: list) -> str:
1704
1702
  "",
1705
1703
  "Known technical debt items:",
1706
1704
  "",
1707
- ]
1705
+ ],
1708
1706
  )
1709
1707
  for p in patterns[:20]:
1710
1708
  lines.append(f"- {p.get('description', str(p))}")
@@ -1714,7 +1712,7 @@ def _generate_claude_rule(category: str, patterns: list) -> str:
1714
1712
  [
1715
1713
  f"## {category.title()} Items",
1716
1714
  "",
1717
- ]
1715
+ ],
1718
1716
  )
1719
1717
  for p in patterns[:20]:
1720
1718
  lines.append(f"- {p.get('description', str(p)[:100])}")
@@ -1723,8 +1721,7 @@ def _generate_claude_rule(category: str, patterns: list) -> str:
1723
1721
 
1724
1722
 
1725
1723
  def _extract_workflow_content(final_output):
1726
- """
1727
- Extract readable content from workflow final_output.
1724
+ """Extract readable content from workflow final_output.
1728
1725
 
1729
1726
  Workflows return their results in various formats - this extracts
1730
1727
  the actual content users want to see.
@@ -1759,11 +1756,11 @@ def _extract_workflow_content(final_output):
1759
1756
  "plan",
1760
1757
  ]
1761
1758
  for key in content_keys:
1762
- if key in final_output and final_output[key]:
1759
+ if final_output.get(key):
1763
1760
  val = final_output[key]
1764
1761
  if isinstance(val, str):
1765
1762
  return val
1766
- elif isinstance(val, dict):
1763
+ if isinstance(val, dict):
1767
1764
  # Recursively extract
1768
1765
  return _extract_workflow_content(val)
1769
1766
 
@@ -1958,29 +1955,26 @@ def cmd_workflow(args):
1958
1955
  "error": error,
1959
1956
  }
1960
1957
  print(json_mod.dumps(output, indent=2))
1958
+ # Display the actual results - this is what users want to see
1959
+ elif result.success:
1960
+ if output_content:
1961
+ print(f"\n{output_content}\n")
1962
+ else:
1963
+ print("\n✓ Workflow completed successfully.\n")
1961
1964
  else:
1962
- # Display the actual results - this is what users want to see
1963
- if result.success:
1964
- if output_content:
1965
- print(f"\n{output_content}\n")
1965
+ # Extract error from various result types
1966
+ error_msg = getattr(result, "error", None)
1967
+ if not error_msg:
1968
+ # Check for blockers (CodeReviewPipelineResult)
1969
+ blockers = getattr(result, "blockers", [])
1970
+ if blockers:
1971
+ error_msg = "; ".join(blockers)
1966
1972
  else:
1967
- print("\n✓ Workflow completed successfully.\n")
1968
- else:
1969
- # Extract error from various result types
1970
- error_msg = getattr(result, "error", None)
1971
- if not error_msg:
1972
- # Check for blockers (CodeReviewPipelineResult)
1973
- blockers = getattr(result, "blockers", [])
1974
- if blockers:
1975
- error_msg = "; ".join(blockers)
1976
- else:
1977
- # Check metadata for error
1978
- metadata = getattr(result, "metadata", {})
1979
- error_msg = (
1980
- metadata.get("error") if isinstance(metadata, dict) else None
1981
- )
1982
- error_msg = error_msg or "Unknown error"
1983
- print(f"\n✗ Workflow failed: {error_msg}\n")
1973
+ # Check metadata for error
1974
+ metadata = getattr(result, "metadata", {})
1975
+ error_msg = metadata.get("error") if isinstance(metadata, dict) else None
1976
+ error_msg = error_msg or "Unknown error"
1977
+ print(f"\n✗ Workflow failed: {error_msg}\n")
1984
1978
 
1985
1979
  except KeyError as e:
1986
1980
  print(f"Error: {e}")
@@ -2059,7 +2053,7 @@ def cmd_frameworks(args):
2059
2053
  json_mod.dumps(
2060
2054
  {"use_case": recommend_use_case, "recommended": recommended.value, **info},
2061
2055
  indent=2,
2062
- )
2056
+ ),
2063
2057
  )
2064
2058
  else:
2065
2059
  print(f"\nRecommended framework for '{recommend_use_case}': {info['name']}")
@@ -2086,7 +2080,7 @@ def cmd_frameworks(args):
2086
2080
  for f in frameworks
2087
2081
  ],
2088
2082
  indent=2,
2089
- )
2083
+ ),
2090
2084
  )
2091
2085
  else:
2092
2086
  print("\n" + "=" * 60)
@@ -2166,32 +2160,45 @@ def main():
2166
2160
  parser_patterns_export.add_argument("input", help="Input file path")
2167
2161
  parser_patterns_export.add_argument("output", help="Output file path")
2168
2162
  parser_patterns_export.add_argument(
2169
- "--input-format", choices=["json", "sqlite"], default="json"
2163
+ "--input-format",
2164
+ choices=["json", "sqlite"],
2165
+ default="json",
2170
2166
  )
2171
2167
  parser_patterns_export.add_argument(
2172
- "--output-format", choices=["json", "sqlite"], default="json"
2168
+ "--output-format",
2169
+ choices=["json", "sqlite"],
2170
+ default="json",
2173
2171
  )
2174
2172
  parser_patterns_export.set_defaults(func=cmd_patterns_export)
2175
2173
 
2176
2174
  # Patterns resolve - mark investigating bugs as resolved
2177
2175
  parser_patterns_resolve = patterns_subparsers.add_parser(
2178
- "resolve", help="Resolve investigating bug patterns"
2176
+ "resolve",
2177
+ help="Resolve investigating bug patterns",
2179
2178
  )
2180
2179
  parser_patterns_resolve.add_argument(
2181
- "bug_id", nargs="?", help="Bug ID to resolve (omit to list investigating)"
2180
+ "bug_id",
2181
+ nargs="?",
2182
+ help="Bug ID to resolve (omit to list investigating)",
2182
2183
  )
2183
2184
  parser_patterns_resolve.add_argument("--root-cause", help="Description of the root cause")
2184
2185
  parser_patterns_resolve.add_argument("--fix", help="Description of the fix applied")
2185
2186
  parser_patterns_resolve.add_argument("--fix-code", help="Code snippet of the fix")
2186
2187
  parser_patterns_resolve.add_argument("--time", type=int, help="Resolution time in minutes")
2187
2188
  parser_patterns_resolve.add_argument(
2188
- "--resolved-by", default="@developer", help="Who resolved it"
2189
+ "--resolved-by",
2190
+ default="@developer",
2191
+ help="Who resolved it",
2189
2192
  )
2190
2193
  parser_patterns_resolve.add_argument(
2191
- "--patterns-dir", default="./patterns", help="Path to patterns directory"
2194
+ "--patterns-dir",
2195
+ default="./patterns",
2196
+ help="Path to patterns directory",
2192
2197
  )
2193
2198
  parser_patterns_resolve.add_argument(
2194
- "--no-regenerate", action="store_true", help="Skip regenerating summary"
2199
+ "--no-regenerate",
2200
+ action="store_true",
2201
+ help="Skip regenerating summary",
2195
2202
  )
2196
2203
  parser_patterns_resolve.set_defaults(func=cmd_patterns_resolve)
2197
2204
 
@@ -2212,7 +2219,9 @@ def main():
2212
2219
  # State list
2213
2220
  parser_state_list = state_subparsers.add_parser("list", help="List saved states")
2214
2221
  parser_state_list.add_argument(
2215
- "--state-dir", default="./empathy_state", help="State directory path"
2222
+ "--state-dir",
2223
+ default="./empathy_state",
2224
+ help="State directory path",
2216
2225
  )
2217
2226
  parser_state_list.set_defaults(func=cmd_state_list)
2218
2227
 
@@ -2221,7 +2230,10 @@ def main():
2221
2230
  parser_run.add_argument("--config", "-c", help="Configuration file path")
2222
2231
  parser_run.add_argument("--user-id", help="User ID (default: cli_user)")
2223
2232
  parser_run.add_argument(
2224
- "--level", type=int, default=4, help="Target empathy level (1-5, default: 4)"
2233
+ "--level",
2234
+ type=int,
2235
+ default=4,
2236
+ help="Target empathy level (1-5, default: 4)",
2225
2237
  )
2226
2238
  parser_run.set_defaults(func=cmd_run)
2227
2239
 
@@ -2235,21 +2247,27 @@ def main():
2235
2247
  parser_inspect.add_argument("--user-id", help="User ID to filter by (optional)")
2236
2248
  parser_inspect.add_argument("--db", help="Database path (default: .empathy/patterns.db)")
2237
2249
  parser_inspect.add_argument(
2238
- "--state-dir", help="State directory path (default: .empathy/state)"
2250
+ "--state-dir",
2251
+ help="State directory path (default: .empathy/state)",
2239
2252
  )
2240
2253
  parser_inspect.set_defaults(func=cmd_inspect)
2241
2254
 
2242
2255
  # Export command
2243
2256
  parser_export = subparsers.add_parser(
2244
- "export", help="Export patterns to file for sharing/backup"
2257
+ "export",
2258
+ help="Export patterns to file for sharing/backup",
2245
2259
  )
2246
2260
  parser_export.add_argument("output", help="Output file path")
2247
2261
  parser_export.add_argument(
2248
- "--user-id", help="User ID to export (optional, exports all if not specified)"
2262
+ "--user-id",
2263
+ help="User ID to export (optional, exports all if not specified)",
2249
2264
  )
2250
2265
  parser_export.add_argument("--db", help="Database path (default: .empathy/patterns.db)")
2251
2266
  parser_export.add_argument(
2252
- "--format", default="json", choices=["json"], help="Export format (default: json)"
2267
+ "--format",
2268
+ default="json",
2269
+ choices=["json"],
2270
+ help="Export format (default: json)",
2253
2271
  )
2254
2272
  parser_export.set_defaults(func=cmd_export)
2255
2273
 
@@ -2261,47 +2279,59 @@ def main():
2261
2279
 
2262
2280
  # Wizard command (Interactive setup)
2263
2281
  parser_wizard = subparsers.add_parser(
2264
- "wizard", help="Interactive setup wizard for creating configuration"
2282
+ "wizard",
2283
+ help="Interactive setup wizard for creating configuration",
2265
2284
  )
2266
2285
  parser_wizard.set_defaults(func=cmd_wizard)
2267
2286
 
2268
2287
  # Provider command (Model provider configuration)
2269
2288
  parser_provider = subparsers.add_parser(
2270
- "provider", help="Configure model providers and hybrid mode"
2289
+ "provider",
2290
+ help="Configure model providers and hybrid mode",
2271
2291
  )
2272
2292
  provider_subparsers = parser_provider.add_subparsers(dest="provider_cmd")
2273
2293
 
2274
2294
  # provider hybrid - Interactive hybrid configuration
2275
2295
  parser_provider_hybrid = provider_subparsers.add_parser(
2276
- "hybrid", help="Configure hybrid mode - pick best models for each tier"
2296
+ "hybrid",
2297
+ help="Configure hybrid mode - pick best models for each tier",
2277
2298
  )
2278
2299
  parser_provider_hybrid.set_defaults(func=cmd_provider_hybrid)
2279
2300
 
2280
2301
  # provider show - Show current configuration
2281
2302
  parser_provider_show = provider_subparsers.add_parser(
2282
- "show", help="Show current provider configuration"
2303
+ "show",
2304
+ help="Show current provider configuration",
2283
2305
  )
2284
2306
  parser_provider_show.set_defaults(func=cmd_provider_show)
2285
2307
 
2286
2308
  # provider set - Quick set single provider
2287
2309
  parser_provider_set = provider_subparsers.add_parser(
2288
- "set", help="Set default provider (anthropic, openai, google, ollama)"
2310
+ "set",
2311
+ help="Set default provider (anthropic, openai, google, ollama)",
2289
2312
  )
2290
2313
  parser_provider_set.add_argument(
2291
- "name", choices=["anthropic", "openai", "google", "ollama", "hybrid"], help="Provider name"
2314
+ "name",
2315
+ choices=["anthropic", "openai", "google", "ollama", "hybrid"],
2316
+ help="Provider name",
2292
2317
  )
2293
2318
  parser_provider_set.set_defaults(func=cmd_provider_set)
2294
2319
 
2295
2320
  # Status command (Session status assistant)
2296
2321
  parser_status = subparsers.add_parser(
2297
- "status", help="Session status - prioritized project status report"
2322
+ "status",
2323
+ help="Session status - prioritized project status report",
2298
2324
  )
2299
2325
  parser_status.add_argument(
2300
- "--patterns-dir", default="./patterns", help="Path to patterns directory"
2326
+ "--patterns-dir",
2327
+ default="./patterns",
2328
+ help="Path to patterns directory",
2301
2329
  )
2302
2330
  parser_status.add_argument("--project-root", default=".", help="Project root directory")
2303
2331
  parser_status.add_argument(
2304
- "--force", action="store_true", help="Force show status regardless of inactivity"
2332
+ "--force",
2333
+ action="store_true",
2334
+ help="Force show status regardless of inactivity",
2305
2335
  )
2306
2336
  parser_status.add_argument("--full", action="store_true", help="Show all items (no limit)")
2307
2337
  parser_status.add_argument("--json", action="store_true", help="Output as JSON")
@@ -2316,7 +2346,8 @@ def main():
2316
2346
 
2317
2347
  # Review command (Pattern-based code review)
2318
2348
  parser_review = subparsers.add_parser(
2319
- "review", help="Pattern-based code review against historical bugs"
2349
+ "review",
2350
+ help="Pattern-based code review against historical bugs",
2320
2351
  )
2321
2352
  parser_review.add_argument("files", nargs="*", help="Files to review (default: recent changes)")
2322
2353
  parser_review.add_argument("--staged", action="store_true", help="Review staged changes only")
@@ -2332,10 +2363,13 @@ def main():
2332
2363
 
2333
2364
  # Health command (Code Health Assistant)
2334
2365
  parser_health = subparsers.add_parser(
2335
- "health", help="Code health assistant - run checks and auto-fix issues"
2366
+ "health",
2367
+ help="Code health assistant - run checks and auto-fix issues",
2336
2368
  )
2337
2369
  parser_health.add_argument(
2338
- "--deep", action="store_true", help="Run comprehensive checks (slower)"
2370
+ "--deep",
2371
+ action="store_true",
2372
+ help="Run comprehensive checks (slower)",
2339
2373
  )
2340
2374
  parser_health.add_argument(
2341
2375
  "--check",
@@ -2344,20 +2378,31 @@ def main():
2344
2378
  )
2345
2379
  parser_health.add_argument("--fix", action="store_true", help="Auto-fix issues where possible")
2346
2380
  parser_health.add_argument(
2347
- "--dry-run", action="store_true", help="Show what would be fixed without applying"
2381
+ "--dry-run",
2382
+ action="store_true",
2383
+ help="Show what would be fixed without applying",
2348
2384
  )
2349
2385
  parser_health.add_argument(
2350
- "--interactive", action="store_true", help="Prompt before applying non-safe fixes"
2386
+ "--interactive",
2387
+ action="store_true",
2388
+ help="Prompt before applying non-safe fixes",
2351
2389
  )
2352
2390
  parser_health.add_argument("--details", action="store_true", help="Show detailed issue list")
2353
2391
  parser_health.add_argument(
2354
- "--full", action="store_true", help="Show full report with all details"
2392
+ "--full",
2393
+ action="store_true",
2394
+ help="Show full report with all details",
2355
2395
  )
2356
2396
  parser_health.add_argument(
2357
- "--trends", type=int, metavar="DAYS", help="Show health trends over N days"
2397
+ "--trends",
2398
+ type=int,
2399
+ metavar="DAYS",
2400
+ help="Show health trends over N days",
2358
2401
  )
2359
2402
  parser_health.add_argument(
2360
- "--project-root", default=".", help="Project root directory (default: current)"
2403
+ "--project-root",
2404
+ default=".",
2405
+ help="Project root directory (default: current)",
2361
2406
  )
2362
2407
  parser_health.add_argument("--json", action="store_true", help="Output as JSON")
2363
2408
  parser_health.set_defaults(func=cmd_health)
@@ -2368,10 +2413,13 @@ def main():
2368
2413
 
2369
2414
  # Morning command (start-of-day briefing)
2370
2415
  parser_morning = subparsers.add_parser(
2371
- "morning", help="Start-of-day briefing with patterns, debt, and focus areas"
2416
+ "morning",
2417
+ help="Start-of-day briefing with patterns, debt, and focus areas",
2372
2418
  )
2373
2419
  parser_morning.add_argument(
2374
- "--patterns-dir", default="./patterns", help="Path to patterns directory"
2420
+ "--patterns-dir",
2421
+ default="./patterns",
2422
+ help="Path to patterns directory",
2375
2423
  )
2376
2424
  parser_morning.add_argument("--project-root", default=".", help="Project root directory")
2377
2425
  parser_morning.add_argument("--verbose", "-v", action="store_true", help="Show detailed output")
@@ -2380,48 +2428,77 @@ def main():
2380
2428
  # Ship command (pre-commit validation)
2381
2429
  parser_ship = subparsers.add_parser("ship", help="Pre-commit validation pipeline")
2382
2430
  parser_ship.add_argument(
2383
- "--patterns-dir", default="./patterns", help="Path to patterns directory"
2431
+ "--patterns-dir",
2432
+ default="./patterns",
2433
+ help="Path to patterns directory",
2384
2434
  )
2385
2435
  parser_ship.add_argument("--project-root", default=".", help="Project root directory")
2386
2436
  parser_ship.add_argument(
2387
- "--skip-sync", action="store_true", help="Skip syncing patterns to Claude"
2437
+ "--skip-sync",
2438
+ action="store_true",
2439
+ help="Skip syncing patterns to Claude",
2440
+ )
2441
+ parser_ship.add_argument(
2442
+ "--tests-only",
2443
+ action="store_true",
2444
+ help="Run tests only (skip lint/format checks)",
2445
+ )
2446
+ parser_ship.add_argument(
2447
+ "--security-only",
2448
+ action="store_true",
2449
+ help="Run security checks only",
2388
2450
  )
2389
2451
  parser_ship.add_argument("--verbose", "-v", action="store_true", help="Show detailed output")
2390
2452
  parser_ship.set_defaults(func=cmd_ship)
2391
2453
 
2392
2454
  # Fix-all command (auto-fix everything)
2393
2455
  parser_fix_all = subparsers.add_parser(
2394
- "fix-all", help="Auto-fix all fixable lint and format issues"
2456
+ "fix-all",
2457
+ help="Auto-fix all fixable lint and format issues",
2395
2458
  )
2396
2459
  parser_fix_all.add_argument("--project-root", default=".", help="Project root directory")
2397
2460
  parser_fix_all.add_argument(
2398
- "--dry-run", action="store_true", help="Show what would be fixed without applying"
2461
+ "--dry-run",
2462
+ action="store_true",
2463
+ help="Show what would be fixed without applying",
2399
2464
  )
2400
2465
  parser_fix_all.add_argument("--verbose", "-v", action="store_true", help="Show detailed output")
2401
2466
  parser_fix_all.set_defaults(func=cmd_fix_all)
2402
2467
 
2403
2468
  # Learn command (pattern learning from git history)
2404
2469
  parser_learn = subparsers.add_parser(
2405
- "learn", help="Learn patterns from git history and bug fixes"
2470
+ "learn",
2471
+ help="Learn patterns from git history and bug fixes",
2406
2472
  )
2407
2473
  parser_learn.add_argument(
2408
- "--patterns-dir", default="./patterns", help="Path to patterns directory"
2474
+ "--patterns-dir",
2475
+ default="./patterns",
2476
+ help="Path to patterns directory",
2409
2477
  )
2410
2478
  parser_learn.add_argument(
2411
- "--analyze", type=int, metavar="N", help="Analyze last N commits (default: 10)"
2479
+ "--analyze",
2480
+ type=int,
2481
+ metavar="N",
2482
+ help="Analyze last N commits (default: 10)",
2412
2483
  )
2413
2484
  parser_learn.add_argument(
2414
- "--watch", action="store_true", help="Watch for new commits (not yet implemented)"
2485
+ "--watch",
2486
+ action="store_true",
2487
+ help="Watch for new commits (not yet implemented)",
2415
2488
  )
2416
2489
  parser_learn.add_argument("--verbose", "-v", action="store_true", help="Show detailed output")
2417
2490
  parser_learn.set_defaults(func=cmd_learn)
2418
2491
 
2419
2492
  # Costs command (cost tracking dashboard)
2420
2493
  parser_costs = subparsers.add_parser(
2421
- "costs", help="View API cost tracking and savings from model routing"
2494
+ "costs",
2495
+ help="View API cost tracking and savings from model routing",
2422
2496
  )
2423
2497
  parser_costs.add_argument(
2424
- "--days", type=int, default=7, help="Number of days to include (default: 7)"
2498
+ "--days",
2499
+ type=int,
2500
+ default=7,
2501
+ help="Number of days to include (default: 7)",
2425
2502
  )
2426
2503
  parser_costs.add_argument("--empathy-dir", default=".empathy", help="Empathy data directory")
2427
2504
  parser_costs.add_argument("--json", action="store_true", help="Output as JSON")
@@ -2443,16 +2520,25 @@ def main():
2443
2520
  # Dashboard command (visual web interface)
2444
2521
  parser_dashboard = subparsers.add_parser("dashboard", help="Launch visual dashboard in browser")
2445
2522
  parser_dashboard.add_argument(
2446
- "--port", type=int, default=8765, help="Port to run on (default: 8765)"
2523
+ "--port",
2524
+ type=int,
2525
+ default=8765,
2526
+ help="Port to run on (default: 8765)",
2447
2527
  )
2448
2528
  parser_dashboard.add_argument(
2449
- "--patterns-dir", default="./patterns", help="Path to patterns directory"
2529
+ "--patterns-dir",
2530
+ default="./patterns",
2531
+ help="Path to patterns directory",
2450
2532
  )
2451
2533
  parser_dashboard.add_argument(
2452
- "--empathy-dir", default=".empathy", help="Empathy data directory"
2534
+ "--empathy-dir",
2535
+ default=".empathy",
2536
+ help="Empathy data directory",
2453
2537
  )
2454
2538
  parser_dashboard.add_argument(
2455
- "--no-browser", action="store_true", help="Don't open browser automatically"
2539
+ "--no-browser",
2540
+ action="store_true",
2541
+ help="Don't open browser automatically",
2456
2542
  )
2457
2543
  parser_dashboard.set_defaults(func=cmd_dashboard)
2458
2544
 
@@ -2462,7 +2548,9 @@ def main():
2462
2548
  help="List and manage agent frameworks (LangChain, LangGraph, AutoGen, Haystack)",
2463
2549
  )
2464
2550
  parser_frameworks.add_argument(
2465
- "--all", action="store_true", help="Show all frameworks including uninstalled"
2551
+ "--all",
2552
+ action="store_true",
2553
+ help="Show all frameworks including uninstalled",
2466
2554
  )
2467
2555
  parser_frameworks.add_argument(
2468
2556
  "--recommend",
@@ -2519,10 +2607,13 @@ def main():
2519
2607
 
2520
2608
  # Sync-claude command (sync patterns to Claude Code)
2521
2609
  parser_sync_claude = subparsers.add_parser(
2522
- "sync-claude", help="Sync learned patterns to Claude Code rules"
2610
+ "sync-claude",
2611
+ help="Sync learned patterns to Claude Code rules",
2523
2612
  )
2524
2613
  parser_sync_claude.add_argument(
2525
- "--patterns-dir", default="./patterns", help="Path to patterns directory"
2614
+ "--patterns-dir",
2615
+ default="./patterns",
2616
+ help="Path to patterns directory",
2526
2617
  )
2527
2618
  parser_sync_claude.add_argument(
2528
2619
  "--output-dir",
@@ -2543,13 +2634,16 @@ def main():
2543
2634
  help="Category to show (getting-started, daily-workflow, code-quality, etc.)",
2544
2635
  )
2545
2636
  parser_cheatsheet.add_argument(
2546
- "--compact", action="store_true", help="Show commands only without descriptions"
2637
+ "--compact",
2638
+ action="store_true",
2639
+ help="Show commands only without descriptions",
2547
2640
  )
2548
2641
  parser_cheatsheet.set_defaults(func=cmd_cheatsheet)
2549
2642
 
2550
2643
  # Onboard command (interactive tutorial)
2551
2644
  parser_onboard = subparsers.add_parser(
2552
- "onboard", help="Interactive onboarding tutorial for new users"
2645
+ "onboard",
2646
+ help="Interactive onboarding tutorial for new users",
2553
2647
  )
2554
2648
  parser_onboard.add_argument("--step", type=int, help="Jump to a specific step (1-5)")
2555
2649
  parser_onboard.add_argument("--reset", action="store_true", help="Reset onboarding progress")
@@ -2557,7 +2651,8 @@ def main():
2557
2651
 
2558
2652
  # Explain command (detailed command explanations)
2559
2653
  parser_explain = subparsers.add_parser(
2560
- "explain", help="Get detailed explanation of how a command works"
2654
+ "explain",
2655
+ help="Get detailed explanation of how a command works",
2561
2656
  )
2562
2657
  parser_explain.add_argument(
2563
2658
  "command",
@@ -2568,7 +2663,8 @@ def main():
2568
2663
 
2569
2664
  # Achievements command (progress tracking)
2570
2665
  parser_achievements = subparsers.add_parser(
2571
- "achievements", help="View your usage statistics and achievements"
2666
+ "achievements",
2667
+ help="View your usage statistics and achievements",
2572
2668
  )
2573
2669
  parser_achievements.set_defaults(func=cmd_achievements)
2574
2670
 
@@ -2587,9 +2683,8 @@ def main():
2587
2683
  pass # Don't fail on discovery errors
2588
2684
 
2589
2685
  return result if result is not None else 0
2590
- else:
2591
- parser.print_help()
2592
- return 0
2686
+ parser.print_help()
2687
+ return 0
2593
2688
 
2594
2689
 
2595
2690
  if __name__ == "__main__":