Spaces:
Sleeping
Sleeping
| """ | |
| SRS Assembler | |
| Deterministic assembly of SRS document from agent outputs, followed by | |
| a single LLM cross-validation pass. Replaces the spec_coordinator agent. | |
| """ | |
| import logging | |
| from datetime import datetime | |
| from langchain_core.prompts import ChatPromptTemplate | |
| from .llm_factory import get_chat_model | |
| from .schemas import TeamRole | |
| logger = logging.getLogger("srs_assembler") | |
| # Static documentation guidelines appendix (replaces technical_writer agent) | |
| STATIC_DOC_APPENDIX = """# Documentation Guidelines | |
| ## Recommended Documentation Structure | |
| ### For Development Teams | |
| 1. **README.md** - Project overview, setup instructions, quick start | |
| 2. **ARCHITECTURE.md** - System architecture, component diagrams, technology decisions | |
| 3. **API.md** - API documentation, endpoint reference, authentication | |
| 4. **DEPLOYMENT.md** - Deployment guide, environment configuration, CI/CD pipeline | |
| 5. **CONTRIBUTING.md** - Coding standards, PR process, code review guidelines | |
| ### For Product Teams | |
| 1. **PRD.md** - Product requirements, user stories, acceptance criteria | |
| 2. **ROADMAP.md** - Feature roadmap, priorities, timeline | |
| 3. **DECISIONS.md** - Architecture decision records (ADRs) | |
| ### Documentation Standards | |
| - Use Markdown format for all documentation | |
| - Keep documentation close to code (in repository) | |
| - Update documentation with every code change | |
| - Use diagrams (Mermaid, PlantUML) for complex concepts | |
| - Maintain a single source of truth | |
| ## Diátaxis Framework | |
| Organize documentation into four categories: | |
| 1. **Tutorials** - Learning-oriented, step-by-step guides | |
| 2. **How-to Guides** - Problem-oriented, practical instructions | |
| 3. **Reference** - Information-oriented, technical specifications | |
| 4. **Explanation** - Understanding-oriented, conceptual background | |
| """ | |
| def assemble_srs( | |
| all_outputs: dict[str, str], | |
| knowledge_graph: dict | None = None, | |
| contradictions: list[dict] | None = None, | |
| ) -> str: | |
| """ | |
| Deterministically assemble SRS document from agent outputs. | |
| Args: | |
| all_outputs: Dictionary mapping role names to their markdown output | |
| knowledge_graph: Optional merged knowledge graph dict for entity context | |
| contradictions: Optional list of cross-agent contradiction dicts | |
| Returns: | |
| Complete SRS document as markdown string | |
| """ | |
| sections = [ | |
| ("1. Product Requirements", all_outputs.get("product_owner", "")), | |
| ("2. Functional Requirements", all_outputs.get("business_analyst", "")), | |
| ("3. Technical Architecture", all_outputs.get("solution_architect", "")), | |
| ("4. Data Architecture", all_outputs.get("data_architect", "")), | |
| ("5. Security Requirements", all_outputs.get("security_analyst", "")), | |
| ("6. User Experience Design", all_outputs.get("ux_designer", "")), | |
| ("7. API Specifications", all_outputs.get("api_designer", "")), | |
| ("8. Testing Strategy", all_outputs.get("qa_strategist", "")), | |
| ("9. DevOps & Infrastructure", all_outputs.get("devops_architect", "")), | |
| ] | |
| # Build table of contents | |
| toc_lines = ["# Software Requirements Specification\n"] | |
| toc_lines.append( | |
| f"**Generated:** {datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S UTC')}\n" | |
| ) | |
| toc_lines.append("---\n") | |
| toc_lines.append("## Table of Contents\n") | |
| for title, _ in sections: | |
| anchor = title.lower().replace(" ", "-").replace(".", "") | |
| toc_lines.append(f"- [{title}](#{anchor})") | |
| toc_lines.append("- [A. Documentation Guidelines](#a-documentation-guidelines)") | |
| if contradictions: | |
| toc_lines.append("- [B. Consistency Warnings](#b-consistency-warnings)") | |
| toc_lines.append("\n---\n") | |
| # Build document body | |
| body_parts = ["\n".join(toc_lines)] | |
| for title, content in sections: | |
| if content and content.strip(): | |
| body_parts.append(f"\n## {title}\n\n{content}\n") | |
| # Add consistency warnings section if contradictions exist | |
| if contradictions: | |
| from .consistency_validator import ConsistencyValidator | |
| validator = ConsistencyValidator() | |
| warnings = validator.format_warnings_section(contradictions) | |
| if warnings: | |
| body_parts.append(f"\n{warnings}\n") | |
| # Add static documentation appendix | |
| body_parts.append(f"\n## A. Documentation Guidelines\n\n{STATIC_DOC_APPENDIX}\n") | |
| return "\n".join(body_parts) | |
| async def validate_srs(srs_document: str, all_outputs: dict[str, str]) -> str: | |
| """ | |
| Cross-validate assembled SRS for internal consistency. | |
| Single LLM pass to check for contradictions, gaps, and completeness. | |
| Args: | |
| srs_document: The assembled SRS document | |
| all_outputs: Original agent outputs for reference | |
| Returns: | |
| Validation report string | |
| """ | |
| validator_prompt = """You are a senior technical reviewer validating a Software Requirements Specification. | |
| Review the assembled SRS below for: | |
| 1. **Internal Consistency**: Are there contradictions between sections? (e.g., architecture says PostgreSQL but data model says MongoDB) | |
| 2. **Completeness**: Are all required sections present and substantive? | |
| 3. **Traceability**: Do requirements link to architecture, tests, and API specs? | |
| 4. **Gaps**: Is there missing critical information? | |
| ## SRS Document | |
| {srs_document} | |
| ## Your Task | |
| Return a validation report in this format: | |
| ```markdown | |
| ## Validation Report | |
| ### Consistency Check | |
| [PASS/FAIL] - [Details] | |
| ### Completeness Check | |
| [PASS/FAIL] - [Details] | |
| ### Traceability Check | |
| [PASS/FAIL] - [Details] | |
| ### Identified Gaps | |
| - [Gap 1] | |
| - [Gap 2] | |
| ### Overall Assessment | |
| [VALID / NEEDS_REVISION] | |
| ``` | |
| Be specific and actionable. If the SRS passes all checks, return "VALID" as the overall assessment.""" | |
| llm = get_chat_model( | |
| role=TeamRole.SPEC_COORDINATOR, temperature=0.2, max_tokens=2048 | |
| ) | |
| prompt_template = ChatPromptTemplate.from_messages( | |
| [ | |
| ("system", validator_prompt), | |
| ("human", "Please validate the SRS document above."), | |
| ] | |
| ) | |
| chain = prompt_template | llm | |
| try: | |
| response = await chain.ainvoke({"srs_document": srs_document[:15000]}) | |
| return response.content if hasattr(response, "content") else str(response) | |
| except Exception as e: | |
| logger.error(f"SRS validation failed: {e}") | |
| return f"## Validation Report\n\n**Status:** Validation failed due to error: {e}\n\n**Recommendation:** Review SRS manually." | |