updated uml diagrams

This commit is contained in:
rob 2025-11-01 11:34:06 -03:00
parent 77248847a8
commit 2862b2ad50
2 changed files with 20 additions and 7 deletions

View File

@ -39,7 +39,7 @@ def get_ai_config() -> dict[str, str]:
Returns dict with 'provider' and 'command' keys. Returns dict with 'provider' and 'command' keys.
""" """
# Try environment first # Try the environment first
provider = os.environ.get("CDEV_AI_PROVIDER") provider = os.environ.get("CDEV_AI_PROVIDER")
command = os.environ.get("CDEV_AI_COMMAND") command = os.environ.get("CDEV_AI_COMMAND")
@ -88,12 +88,12 @@ def call_ai_cli(prompt: str, content: str) -> dict[str, Any] | None:
config = get_ai_config() config = get_ai_config()
command_template = config["command"] command_template = config["command"]
# Create temporary file in .git/ai-agents-temp/ (accessible to Claude CLI) # Create a temporary file in .git/ai-agents-temp/ (accessible to Claude CLI)
# Using .git/ ensures it's gitignored and Claude has permission # Using .git/ ensures it's gitignored and Claude has permission
temp_dir = Path.cwd() / ".git" / "ai-agents-temp" temp_dir = Path.cwd() / ".git" / "ai-agents-temp"
temp_dir.mkdir(parents=True, exist_ok=True) temp_dir.mkdir(parents=True, exist_ok=True)
# Use PID for unique filename to avoid conflicts # Use PID for a unique filename to avoid conflicts
content_file = temp_dir / f"discussion-{os.getpid()}.md" content_file = temp_dir / f"discussion-{os.getpid()}.md"
content_file.write_text(content, encoding='utf-8') content_file.write_text(content, encoding='utf-8')
@ -211,7 +211,7 @@ def call_ai_api(prompt: str, content: str) -> dict[str, Any] | None:
def call_ai(prompt: str, content: str) -> dict[str, Any] | None: def call_ai(prompt: str, content: str) -> dict[str, Any] | None:
""" """
Call configured AI provider (CLI or API). Call a configured AI provider (CLI or API).
First tries CLI-based provider (claude, gemini, codex). First tries CLI-based provider (claude, gemini, codex).
Falls back to direct API if ANTHROPIC_API_KEY is set. Falls back to direct API if ANTHROPIC_API_KEY is set.
@ -241,9 +241,9 @@ def call_ai(prompt: str, content: str) -> dict[str, Any] | None:
def normalize_discussion(content: str) -> dict[str, Any] | None: def normalize_discussion(content: str) -> dict[str, Any] | None:
""" """
Agent 1: Normalize natural language discussion to structured format. Agent 1: Normalize natural language discussion to a structured format.
Extracts votes, questions, decisions, action items in consistent format. Extracts votes, questions, decisions, action items in a consistent format.
""" """
prompt = """You are a discussion normalizer. Extract structured information from the discussion content. prompt = """You are a discussion normalizer. Extract structured information from the discussion content.

View File

@ -23,6 +23,9 @@ def get_staged_files(repo_root: Path) -> list[Path]:
""" """
Return staged (added/modified) paths relative to the repository root. Return staged (added/modified) paths relative to the repository root.
""" """
# We only care about what is in the index; the working tree may include
# experiments the developer does not intend to commit. `--diff-filter=AM`
# narrows the list to new or modified files.
result = run( result = run(
["git", "diff", "--cached", "--name-only", "--diff-filter=AM"], ["git", "diff", "--cached", "--name-only", "--diff-filter=AM"],
cwd=repo_root, cwd=repo_root,
@ -42,18 +45,21 @@ def merge_instructions(source_instr: str, output_instr: str, append_instr: str)
if append_instr: if append_instr:
prefix = (final + "\n\n") if final else "" prefix = (final + "\n\n") if final else ""
final = f"{prefix}Additional requirements for this output location:\n{append_instr}" final = f"{prefix}Additional requirements for this output location:\n{append_instr}"
return final.strip() return final.strip() # Final, human-readable instruction block handed to the AI
def process(repo_root: Path, rules: RulesConfig, model: ModelConfig) -> int: def process(repo_root: Path, rules: RulesConfig, model: ModelConfig) -> int:
""" """
Walk staged files, resolve matching outputs, and invoke the patcher for each. Walk staged files, resolve matching outputs, and invoke the patcher for each.
""" """
# 1) Gather the staged file list (Git index only).
staged_files = get_staged_files(repo_root) staged_files = get_staged_files(repo_root)
if not staged_files: if not staged_files:
return 0 return 0
# 2) For each staged file, look up the matching rule and iterate outputs.
for src_rel in staged_files: for src_rel in staged_files:
# Find the most specific rule (nearest .ai-rules.yml wins).
rule_name = rules.get_rule_name(src_rel) rule_name = rules.get_rule_name(src_rel)
if not rule_name: if not rule_name:
continue continue
@ -79,6 +85,9 @@ def process(repo_root: Path, rules: RulesConfig, model: ModelConfig) -> int:
print(f"[runner] skipping {output_name}: unsafe path {rendered_path}", file=sys.stderr) print(f"[runner] skipping {output_name}: unsafe path {rendered_path}", file=sys.stderr)
continue continue
# Build the instruction set for this output. Output-specific text
# overrides the rule-level text, and we keep the source version as a
# fallback.
instruction = output_cfg.get("instruction", "") or source_instruction instruction = output_cfg.get("instruction", "") or source_instruction
append = output_cfg.get("instruction_append", "") append = output_cfg.get("instruction_append", "")
@ -90,6 +99,7 @@ def process(repo_root: Path, rules: RulesConfig, model: ModelConfig) -> int:
final_instruction = merge_instructions(source_instruction, instruction, append) final_instruction = merge_instructions(source_instruction, instruction, append)
# 3) Ask the patcher to build a diff with the assembled instruction.
try: try:
generate_output( generate_output(
repo_root=repo_root, repo_root=repo_root,
@ -109,10 +119,12 @@ def main(argv: list[str] | None = None) -> int:
""" """
CLI entry point used by the pre-commit hook. CLI entry point used by the pre-commit hook.
""" """
# Parse command-line options (only --model override today).
parser = argparse.ArgumentParser(description="CascadingDev AI runner") parser = argparse.ArgumentParser(description="CascadingDev AI runner")
parser.add_argument("--model", help="Override AI command (default from env)") parser.add_argument("--model", help="Override AI command (default from env)")
args = parser.parse_args(argv) args = parser.parse_args(argv)
# Load the nearest .ai-rules.yml (fail quietly if missing).
repo_root = Path.cwd().resolve() repo_root = Path.cwd().resolve()
try: try:
rules = RulesConfig.load(repo_root) rules = RulesConfig.load(repo_root)
@ -120,6 +132,7 @@ def main(argv: list[str] | None = None) -> int:
print("[runner] .ai-rules.yml not found; skipping") print("[runner] .ai-rules.yml not found; skipping")
return 0 return 0
# Instantiate the model config and delegate to the processing pipeline.
model = ModelConfig(command=args.model or ModelConfig().command) model = ModelConfig(command=args.model or ModelConfig().command)
return process(repo_root, rules, model) return process(repo_root, rules, model)