requirements-agent 0.0.1__tar.gz

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 (63) hide show
  1. requirements_agent-0.0.1/PKG-INFO +166 -0
  2. requirements_agent-0.0.1/README.md +143 -0
  3. requirements_agent-0.0.1/pyproject.toml +41 -0
  4. requirements_agent-0.0.1/setup.cfg +4 -0
  5. requirements_agent-0.0.1/src/requirements_agent/__init__.py +3 -0
  6. requirements_agent-0.0.1/src/requirements_agent/agent.py +143 -0
  7. requirements_agent-0.0.1/src/requirements_agent/cli.py +435 -0
  8. requirements_agent-0.0.1/src/requirements_agent/config.py +360 -0
  9. requirements_agent-0.0.1/src/requirements_agent/context/__init__.py +3 -0
  10. requirements_agent-0.0.1/src/requirements_agent/context/aggregate.py +136 -0
  11. requirements_agent-0.0.1/src/requirements_agent/context/base.py +14 -0
  12. requirements_agent-0.0.1/src/requirements_agent/context/folder.py +107 -0
  13. requirements_agent-0.0.1/src/requirements_agent/context/mcp.py +22 -0
  14. requirements_agent-0.0.1/src/requirements_agent/context/rag.py +22 -0
  15. requirements_agent-0.0.1/src/requirements_agent/export/__init__.py +3 -0
  16. requirements_agent-0.0.1/src/requirements_agent/export/markdown.py +53 -0
  17. requirements_agent-0.0.1/src/requirements_agent/export/pdf.py +82 -0
  18. requirements_agent-0.0.1/src/requirements_agent/init_cmd.py +191 -0
  19. requirements_agent-0.0.1/src/requirements_agent/llm/__init__.py +3 -0
  20. requirements_agent-0.0.1/src/requirements_agent/llm/base.py +47 -0
  21. requirements_agent-0.0.1/src/requirements_agent/llm/mock.py +116 -0
  22. requirements_agent-0.0.1/src/requirements_agent/llm/providers.py +127 -0
  23. requirements_agent-0.0.1/src/requirements_agent/llm/router.py +19 -0
  24. requirements_agent-0.0.1/src/requirements_agent/models.py +62 -0
  25. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/agents/analyst.md +29 -0
  26. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/agents/architect.md +28 -0
  27. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/agents/bmad-orchestrator.md +26 -0
  28. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/agents/dev.md +27 -0
  29. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/agents/pm.md +27 -0
  30. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/agents/po.md +27 -0
  31. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/agents/qa.md +28 -0
  32. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/agents/sm.md +26 -0
  33. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/checklists/spec-circuit-analyst.md +8 -0
  34. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/checklists/spec-circuit-architect.md +11 -0
  35. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/checklists/spec-circuit-dev.md +11 -0
  36. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/checklists/spec-circuit-orchestrator.md +9 -0
  37. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/checklists/spec-circuit-pm.md +9 -0
  38. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/checklists/spec-circuit-po.md +10 -0
  39. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/checklists/spec-circuit-qa.md +11 -0
  40. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/checklists/spec-circuit-sm.md +8 -0
  41. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/data/bmad-kb.md +19 -0
  42. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/data/requirements-standards-baseline.md +188 -0
  43. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/data/technical-preferences.md +54 -0
  44. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/utils/template-format.md +7 -0
  45. requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/workflows/greenfield-fullstack.yml +177 -0
  46. requirements_agent-0.0.1/src/requirements_agent/pipeline/__init__.py +3 -0
  47. requirements_agent-0.0.1/src/requirements_agent/pipeline/brd.py +66 -0
  48. requirements_agent-0.0.1/src/requirements_agent/pipeline/pack.py +233 -0
  49. requirements_agent-0.0.1/src/requirements_agent/pipeline/prompts.py +124 -0
  50. requirements_agent-0.0.1/src/requirements_agent/pipeline/quality.py +102 -0
  51. requirements_agent-0.0.1/src/requirements_agent/pipeline/refine.py +234 -0
  52. requirements_agent-0.0.1/src/requirements_agent/pipeline/spec_circuit.py +146 -0
  53. requirements_agent-0.0.1/src/requirements_agent/tui/__init__.py +3 -0
  54. requirements_agent-0.0.1/src/requirements_agent/tui/app.py +351 -0
  55. requirements_agent-0.0.1/src/requirements_agent/tui/screens/__init__.py +3 -0
  56. requirements_agent-0.0.1/src/requirements_agent/tuios_hook.py +41 -0
  57. requirements_agent-0.0.1/src/requirements_agent.egg-info/PKG-INFO +166 -0
  58. requirements_agent-0.0.1/src/requirements_agent.egg-info/SOURCES.txt +61 -0
  59. requirements_agent-0.0.1/src/requirements_agent.egg-info/dependency_links.txt +1 -0
  60. requirements_agent-0.0.1/src/requirements_agent.egg-info/entry_points.txt +2 -0
  61. requirements_agent-0.0.1/src/requirements_agent.egg-info/requires.txt +18 -0
  62. requirements_agent-0.0.1/src/requirements_agent.egg-info/top_level.txt +1 -0
  63. requirements_agent-0.0.1/tests/test_pipeline.py +116 -0
@@ -0,0 +1,166 @@
1
+ Metadata-Version: 2.4
2
+ Name: requirements-agent
3
+ Version: 0.0.1
4
+ Summary: Self-contained Spec Circuit Requirements Agent (CLI + Textual TUI)
5
+ Author: CLI-Agents
6
+ License: MIT
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: typer>=0.12
10
+ Requires-Dist: rich>=13.7
11
+ Requires-Dist: textual>=0.80
12
+ Requires-Dist: openai>=1.40
13
+ Requires-Dist: httpx>=0.27
14
+ Requires-Dist: pyyaml>=6.0
15
+ Requires-Dist: tomli>=2.0; python_version < "3.11"
16
+ Requires-Dist: fpdf2>=2.7
17
+ Requires-Dist: markdown>=3.5
18
+ Provides-Extra: pdf
19
+ Requires-Dist: weasyprint>=62.0; extra == "pdf"
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest>=8.0; extra == "dev"
22
+ Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
23
+
24
+ # Requirements Agent
25
+
26
+ Self-contained **Spec Circuit** requirements agent: multi-persona BMAD review → quality score → refine → BRD → Markdown/PDF.
27
+
28
+ No Atlas / FastAPI / Mongo dependency. Configure LLMs in JSON, agent settings in YAML, run from CLI or Textual TUI.
29
+
30
+ ## Install & init
31
+
32
+ ```bash
33
+ cd Requirement_Agent
34
+ pip install -e ".[dev]"
35
+
36
+ # Scaffold config in the current directory
37
+ req-agent init
38
+
39
+ # Or into ~/.config/requirements-agent/
40
+ req-agent init --global
41
+ ```
42
+
43
+ ### npm launcher (optional)
44
+
45
+ The agent is Python. For `npx` / npm discoverability there is a thin wrapper in [`npm/`](npm/):
46
+
47
+ ```bash
48
+ cd npm && npm install && npm link
49
+ npx req-agent --help
50
+ ```
51
+
52
+ Publish **PyPI** for the real package; publish **npm** only as the launcher (see [`npm/README.md`](npm/README.md)).
53
+
54
+ One-shot release (same version on both registries; assumes you already ran `twine`/`npm` login):
55
+
56
+ ```bash
57
+ ./scripts/publish.sh # current pyproject version
58
+ ./scripts/publish.sh 0.2.0 # bump + publish
59
+ ./scripts/publish.sh --dry-run # build only
60
+ ```
61
+
62
+ `init` writes:
63
+
64
+ | File | Purpose |
65
+ |------|---------|
66
+ | `requirements-agent.yaml` | Agent settings (context, prompts, export, active LLM profile) |
67
+ | `llms.json` | Named LLM profiles (multiple models/providers) |
68
+ | `.env.example` | Env var cheat-sheet for API keys |
69
+
70
+ ## Configure LLMs (`llms.json`)
71
+
72
+ ```json
73
+ {
74
+ "default": "azure-gpt4o",
75
+ "models": {
76
+ "azure-gpt4o": {
77
+ "provider": "azure",
78
+ "model": "gpt-4o",
79
+ "deployment": "gpt-4o",
80
+ "endpoint": "https://YOUR.openai.azure.com/",
81
+ "api_key_env": "RA_AZURE_API_KEY",
82
+ "temperature": 0.3
83
+ },
84
+ "ollama-llama": {
85
+ "provider": "ollama",
86
+ "model": "llama3.2",
87
+ "endpoint": "http://127.0.0.1:11434/v1"
88
+ },
89
+ "mock": { "provider": "mock", "model": "mock" }
90
+ }
91
+ }
92
+ ```
93
+
94
+ List profiles: `req-agent models`
95
+
96
+ ## Configure agent (`requirements-agent.yaml`)
97
+
98
+ ```yaml
99
+ llm:
100
+ models_file: ./llms.json
101
+ active: azure-gpt4o # or override with --profile
102
+
103
+ context:
104
+ providers: [folder]
105
+ folder_paths: [./docs]
106
+
107
+ prompts:
108
+ personas:
109
+ architect:
110
+ system_extra: "Emphasize zero-trust boundaries."
111
+
112
+ export:
113
+ default_format: both
114
+ out_dir: ./out
115
+ ```
116
+
117
+ Examples: [`config.example.yaml`](config.example.yaml), [`llms.example.json`](llms.example.json). Legacy TOML still loads if present.
118
+
119
+ Env overrides: `RA_CONFIG`, `RA_LLMS_JSON`, `RA_LLM_PROFILE`, `RA_LLM_PROVIDER`, `RA_LLM_MODEL`, `RA_API_KEY` / `OPENAI_API_KEY` / `RA_AZURE_*`.
120
+
121
+ ## CLI
122
+
123
+ ```bash
124
+ # Offline dry-run
125
+ req-agent run \
126
+ --title "Identity Hub SSO" \
127
+ --design-file ./brief.md \
128
+ --profile mock \
129
+ --format both \
130
+ --out ./out/identity-hub
131
+
132
+ # Use a named profile from llms.json
133
+ req-agent run --profile azure-gpt4o --title "..." --design-file brief.md
134
+
135
+ # Interactive TUI
136
+ req-agent tui --profile mock
137
+
138
+ # Stages
139
+ req-agent review --title "..." --design-file brief.md --out ./out
140
+ req-agent score --title "..." --design-file brief.md --report ./out/01-spec-circuit-report.md
141
+ req-agent refine --title "..." --design-file brief.md --report ./out/01-spec-circuit-report.md \
142
+ --message "Add measurable NFRs" --out ./out/01-refined.md
143
+ req-agent consolidate --title "..." --design-file brief.md --report ./out/01-refined.md \
144
+ --out ./out/02-requirements-report.md
145
+ req-agent export --report ./out/02-requirements-report.md --out ./out/report --format both
146
+ ```
147
+
148
+ ## Context injection
149
+
150
+ | Provider | v1 |
151
+ |----------|----|
152
+ | **folder** | `--attach` / `--context-dir` / `folder_paths` |
153
+ | **rag** | Stub (phase 2) |
154
+ | **mcp** | Stub (phase 2) |
155
+
156
+ ## Personas
157
+
158
+ Eight BMAD roles (vendored `bmad-core-spec`): orchestrator → analyst → pm → po → architect → dev → qa → sm.
159
+
160
+ ## TUIOS
161
+
162
+ Optional: when running inside [tuios](https://github.com/Gaurav-Gosain/tuios), the agent calls `tuios set-agent-state`. Force with `RA_TUIOS_HOOK=1`.
163
+
164
+ ## vs Atlas Requirements Architect
165
+
166
+ Same Spec Circuit brain and BMAD pack; Memory AI → local folder (future RAG/MCP); LLMs from `llms.json` instead of Mongo Settings. See [`REQUIREMENTS_ARCHITECT.md`](REQUIREMENTS_ARCHITECT.md).
@@ -0,0 +1,143 @@
1
+ # Requirements Agent
2
+
3
+ Self-contained **Spec Circuit** requirements agent: multi-persona BMAD review → quality score → refine → BRD → Markdown/PDF.
4
+
5
+ No Atlas / FastAPI / Mongo dependency. Configure LLMs in JSON, agent settings in YAML, run from CLI or Textual TUI.
6
+
7
+ ## Install & init
8
+
9
+ ```bash
10
+ cd Requirement_Agent
11
+ pip install -e ".[dev]"
12
+
13
+ # Scaffold config in the current directory
14
+ req-agent init
15
+
16
+ # Or into ~/.config/requirements-agent/
17
+ req-agent init --global
18
+ ```
19
+
20
+ ### npm launcher (optional)
21
+
22
+ The agent is Python. For `npx` / npm discoverability there is a thin wrapper in [`npm/`](npm/):
23
+
24
+ ```bash
25
+ cd npm && npm install && npm link
26
+ npx req-agent --help
27
+ ```
28
+
29
+ Publish **PyPI** for the real package; publish **npm** only as the launcher (see [`npm/README.md`](npm/README.md)).
30
+
31
+ One-shot release (same version on both registries; assumes you already ran `twine`/`npm` login):
32
+
33
+ ```bash
34
+ ./scripts/publish.sh # current pyproject version
35
+ ./scripts/publish.sh 0.2.0 # bump + publish
36
+ ./scripts/publish.sh --dry-run # build only
37
+ ```
38
+
39
+ `init` writes:
40
+
41
+ | File | Purpose |
42
+ |------|---------|
43
+ | `requirements-agent.yaml` | Agent settings (context, prompts, export, active LLM profile) |
44
+ | `llms.json` | Named LLM profiles (multiple models/providers) |
45
+ | `.env.example` | Env var cheat-sheet for API keys |
46
+
47
+ ## Configure LLMs (`llms.json`)
48
+
49
+ ```json
50
+ {
51
+ "default": "azure-gpt4o",
52
+ "models": {
53
+ "azure-gpt4o": {
54
+ "provider": "azure",
55
+ "model": "gpt-4o",
56
+ "deployment": "gpt-4o",
57
+ "endpoint": "https://YOUR.openai.azure.com/",
58
+ "api_key_env": "RA_AZURE_API_KEY",
59
+ "temperature": 0.3
60
+ },
61
+ "ollama-llama": {
62
+ "provider": "ollama",
63
+ "model": "llama3.2",
64
+ "endpoint": "http://127.0.0.1:11434/v1"
65
+ },
66
+ "mock": { "provider": "mock", "model": "mock" }
67
+ }
68
+ }
69
+ ```
70
+
71
+ List profiles: `req-agent models`
72
+
73
+ ## Configure agent (`requirements-agent.yaml`)
74
+
75
+ ```yaml
76
+ llm:
77
+ models_file: ./llms.json
78
+ active: azure-gpt4o # or override with --profile
79
+
80
+ context:
81
+ providers: [folder]
82
+ folder_paths: [./docs]
83
+
84
+ prompts:
85
+ personas:
86
+ architect:
87
+ system_extra: "Emphasize zero-trust boundaries."
88
+
89
+ export:
90
+ default_format: both
91
+ out_dir: ./out
92
+ ```
93
+
94
+ Examples: [`config.example.yaml`](config.example.yaml), [`llms.example.json`](llms.example.json). Legacy TOML still loads if present.
95
+
96
+ Env overrides: `RA_CONFIG`, `RA_LLMS_JSON`, `RA_LLM_PROFILE`, `RA_LLM_PROVIDER`, `RA_LLM_MODEL`, `RA_API_KEY` / `OPENAI_API_KEY` / `RA_AZURE_*`.
97
+
98
+ ## CLI
99
+
100
+ ```bash
101
+ # Offline dry-run
102
+ req-agent run \
103
+ --title "Identity Hub SSO" \
104
+ --design-file ./brief.md \
105
+ --profile mock \
106
+ --format both \
107
+ --out ./out/identity-hub
108
+
109
+ # Use a named profile from llms.json
110
+ req-agent run --profile azure-gpt4o --title "..." --design-file brief.md
111
+
112
+ # Interactive TUI
113
+ req-agent tui --profile mock
114
+
115
+ # Stages
116
+ req-agent review --title "..." --design-file brief.md --out ./out
117
+ req-agent score --title "..." --design-file brief.md --report ./out/01-spec-circuit-report.md
118
+ req-agent refine --title "..." --design-file brief.md --report ./out/01-spec-circuit-report.md \
119
+ --message "Add measurable NFRs" --out ./out/01-refined.md
120
+ req-agent consolidate --title "..." --design-file brief.md --report ./out/01-refined.md \
121
+ --out ./out/02-requirements-report.md
122
+ req-agent export --report ./out/02-requirements-report.md --out ./out/report --format both
123
+ ```
124
+
125
+ ## Context injection
126
+
127
+ | Provider | v1 |
128
+ |----------|----|
129
+ | **folder** | `--attach` / `--context-dir` / `folder_paths` |
130
+ | **rag** | Stub (phase 2) |
131
+ | **mcp** | Stub (phase 2) |
132
+
133
+ ## Personas
134
+
135
+ Eight BMAD roles (vendored `bmad-core-spec`): orchestrator → analyst → pm → po → architect → dev → qa → sm.
136
+
137
+ ## TUIOS
138
+
139
+ Optional: when running inside [tuios](https://github.com/Gaurav-Gosain/tuios), the agent calls `tuios set-agent-state`. Force with `RA_TUIOS_HOOK=1`.
140
+
141
+ ## vs Atlas Requirements Architect
142
+
143
+ Same Spec Circuit brain and BMAD pack; Memory AI → local folder (future RAG/MCP); LLMs from `llms.json` instead of Mongo Settings. See [`REQUIREMENTS_ARCHITECT.md`](REQUIREMENTS_ARCHITECT.md).
@@ -0,0 +1,41 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "requirements-agent"
7
+ version = "0.0.1"
8
+ description = "Self-contained Spec Circuit Requirements Agent (CLI + Textual TUI)"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "CLI-Agents" }]
13
+ dependencies = [
14
+ "typer>=0.12",
15
+ "rich>=13.7",
16
+ "textual>=0.80",
17
+ "openai>=1.40",
18
+ "httpx>=0.27",
19
+ "pyyaml>=6.0",
20
+ "tomli>=2.0; python_version < '3.11'",
21
+ "fpdf2>=2.7",
22
+ "markdown>=3.5",
23
+ ]
24
+
25
+ [project.optional-dependencies]
26
+ pdf = ["weasyprint>=62.0"]
27
+ dev = ["pytest>=8.0", "pytest-asyncio>=0.23"]
28
+
29
+ [project.scripts]
30
+ req-agent = "requirements_agent.cli:app"
31
+
32
+ [tool.setuptools.packages.find]
33
+ where = ["src"]
34
+
35
+ [tool.setuptools.package-data]
36
+ requirements_agent = ["packs/**/*"]
37
+
38
+ [tool.pytest.ini_options]
39
+ asyncio_mode = "auto"
40
+ testpaths = ["tests"]
41
+ pythonpath = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ """Self-contained Spec Circuit Requirements Agent."""
2
+
3
+ __version__ = "0.0.1"
@@ -0,0 +1,143 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+ from typing import Any, Callable, Dict, List, Optional
5
+
6
+ from requirements_agent.config import AppConfig
7
+ from requirements_agent.export.markdown import export_run_artifacts
8
+ from requirements_agent.export.pdf import export_pdf
9
+ from requirements_agent.llm.base import LlmClient
10
+ from requirements_agent.llm.router import build_llm_client
11
+ from requirements_agent.models import QualityScore, ReviewResult
12
+ from requirements_agent.pipeline.brd import BRDConsolidator
13
+ from requirements_agent.pipeline.quality import QualityScorer
14
+ from requirements_agent.pipeline.refine import ReportRefiner
15
+ from requirements_agent.pipeline.spec_circuit import SpecCircuitService
16
+ from requirements_agent.tuios_hook import set_agent_state
17
+
18
+
19
+ ProgressCallback = Callable[[Dict[str, Any]], None]
20
+
21
+
22
+ class RequirementsAgent:
23
+ def __init__(self, config: AppConfig, llm: Optional[LlmClient] = None, *, extra_paths: Optional[List[str]] = None):
24
+ self.config = config
25
+ self.llm = llm or build_llm_client(config.llm)
26
+ self.extra_paths = list(extra_paths or [])
27
+ self.spec = SpecCircuitService.from_app_config(config, self.llm, extra_folder_paths=self.extra_paths)
28
+ self.quality = QualityScorer(self.llm, self.spec.context)
29
+ self.refiner = ReportRefiner(self.llm, self.spec.context)
30
+ self.brd = BRDConsolidator(self.llm, self.spec.context)
31
+
32
+ def review(self, title: str, design: str, *, on_progress: Optional[ProgressCallback] = None) -> ReviewResult:
33
+ set_agent_state("working", detail="Spec Circuit review")
34
+ try:
35
+ return self.spec.review(title, design, on_progress=on_progress)
36
+ finally:
37
+ set_agent_state("idle")
38
+
39
+ def score(
40
+ self,
41
+ title: str,
42
+ design: str,
43
+ report: str,
44
+ *,
45
+ refinement_context: str = "",
46
+ ) -> QualityScore:
47
+ set_agent_state("working", detail="Quality score")
48
+ try:
49
+ return self.quality.score(title, design, report, refinement_context=refinement_context)
50
+ finally:
51
+ set_agent_state("idle")
52
+
53
+ def refine(self, title: str, design: str, report: str, message: str, *, history=None) -> Dict[str, Any]:
54
+ set_agent_state("working", detail="Refine report")
55
+ try:
56
+ return self.refiner.refine(title, design, report, message, history=history)
57
+ finally:
58
+ set_agent_state("idle")
59
+
60
+ def questions(self, title: str, design: str, report: str) -> Dict[str, Any]:
61
+ set_agent_state("working", detail="Extract questions")
62
+ try:
63
+ return self.refiner.extract_open_questions(title, design, report)
64
+ finally:
65
+ set_agent_state("idle")
66
+
67
+ def resolve(self, title: str, design: str, report: str, question: str) -> Dict[str, Any]:
68
+ set_agent_state("working", detail="Suggest resolution")
69
+ try:
70
+ return self.refiner.suggest_question_resolution(title, design, report, question)
71
+ finally:
72
+ set_agent_state("idle")
73
+
74
+ def consolidate(self, title: str, design: str, report: str) -> Dict[str, Any]:
75
+ set_agent_state("working", detail="BRD consolidation")
76
+ try:
77
+ return self.brd.consolidate(title, design, report)
78
+ finally:
79
+ set_agent_state("idle")
80
+
81
+ def run(
82
+ self,
83
+ title: str,
84
+ design: str,
85
+ *,
86
+ out_dir: Optional[Path] = None,
87
+ export_format: Optional[str] = None,
88
+ consolidate: bool = True,
89
+ on_progress: Optional[ProgressCallback] = None,
90
+ ) -> Dict[str, Any]:
91
+ out = Path(out_dir or self.config.export.out_dir).expanduser()
92
+ fmt = (export_format or self.config.export.default_format or "md").lower()
93
+
94
+ review = self.review(title, design, on_progress=on_progress)
95
+ if not review.success:
96
+ return {"success": False, "error": review.error}
97
+
98
+ quality = self.score(title, design, review.report_markdown)
99
+ brd_md = None
100
+ if consolidate:
101
+ brd_result = self.consolidate(title, design, review.report_markdown)
102
+ if brd_result.get("success"):
103
+ brd_md = brd_result["report_markdown"]
104
+
105
+ quality_dict = {
106
+ "overall_score": quality.overall_score,
107
+ "dimensions": quality.dimensions,
108
+ "rationale": quality.rationale,
109
+ "top_gaps": quality.top_gaps,
110
+ "success": quality.success,
111
+ "error": quality.error,
112
+ }
113
+ paths = export_run_artifacts(
114
+ out,
115
+ spec_circuit=review.report_markdown,
116
+ brd=brd_md,
117
+ quality=quality_dict,
118
+ sections=review.sections,
119
+ meta={
120
+ "title": title,
121
+ "provider": self.config.llm.provider,
122
+ "model": self.config.llm.model,
123
+ "context": review.context.summary() if review.context else None,
124
+ },
125
+ )
126
+
127
+ pdf_paths = []
128
+ if fmt in ("pdf", "both"):
129
+ if review.report_markdown:
130
+ p = export_pdf(review.report_markdown, out / "01-spec-circuit-report.pdf", title=title)
131
+ pdf_paths.append(str(p))
132
+ if brd_md:
133
+ p = export_pdf(brd_md, out / "02-requirements-report.pdf", title=f"{title} — BRD")
134
+ pdf_paths.append(str(p))
135
+ paths["pdf"] = pdf_paths
136
+
137
+ return {
138
+ "success": True,
139
+ "paths": paths,
140
+ "quality": quality_dict,
141
+ "report_markdown": review.report_markdown,
142
+ "brd_markdown": brd_md,
143
+ }