ref-agents 1.0.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.
- ref_agents/__init__.py +9 -0
- ref_agents/api_keys.json.example +8 -0
- ref_agents/auth.py +129 -0
- ref_agents/codemap/..md +62 -0
- ref_agents/codemap/CODE_MAP.md +37 -0
- ref_agents/codemap/core.md +43 -0
- ref_agents/codemap/models.md +43 -0
- ref_agents/codemap/prompts.md +40 -0
- ref_agents/codemap/security.md +45 -0
- ref_agents/codemap/tools.md +94 -0
- ref_agents/codemap/tools_browser.md +44 -0
- ref_agents/codemap/utils.md +42 -0
- ref_agents/codemap/workflow.md +42 -0
- ref_agents/config/ai_patterns.yaml +101 -0
- ref_agents/config/frameworks/angular.yaml +104 -0
- ref_agents/config/frameworks/aspnet.yaml +84 -0
- ref_agents/config/frameworks/ef_core.yaml +81 -0
- ref_agents/config/frameworks/react.yaml +111 -0
- ref_agents/config/frameworks/spring_boot.yaml +117 -0
- ref_agents/config/languages/csharp.yaml +153 -0
- ref_agents/config/languages/java.yaml +188 -0
- ref_agents/config/languages/javascript.yaml +172 -0
- ref_agents/config/languages/python.yaml +153 -0
- ref_agents/config/languages/typescript.yaml +193 -0
- ref_agents/constants.py +553 -0
- ref_agents/core/__init__.py +15 -0
- ref_agents/core/config_loader.py +160 -0
- ref_agents/core/config_models.py +167 -0
- ref_agents/core/config_parsing.py +84 -0
- ref_agents/core/language_detector.py +388 -0
- ref_agents/core/validation_models.py +66 -0
- ref_agents/core/validation_primitives.py +176 -0
- ref_agents/errors.py +34 -0
- ref_agents/license_client.py +247 -0
- ref_agents/models/__init__.py +22 -0
- ref_agents/models/gherkin.py +45 -0
- ref_agents/models/hierarchy.py +80 -0
- ref_agents/models/invest.py +59 -0
- ref_agents/models/version.py +49 -0
- ref_agents/prompts/__init__.py +9 -0
- ref_agents/prompts/start_agent.py +772 -0
- ref_agents/rules/architecture/backend_patterns.md +43 -0
- ref_agents/rules/architecture/diagramming.md +100 -0
- ref_agents/rules/architecture/frontend_patterns.md +40 -0
- ref_agents/rules/architecture/impact_analysis.md +129 -0
- ref_agents/rules/architecture/migration_strategy.md +208 -0
- ref_agents/rules/architecture/regression_protocol.md +77 -0
- ref_agents/rules/architecture/system_design.md +97 -0
- ref_agents/rules/common/codemap_standard.md +97 -0
- ref_agents/rules/common/core_protocol.md +59 -0
- ref_agents/rules/common/prompt_engineering.md +294 -0
- ref_agents/rules/development/debugging.md +32 -0
- ref_agents/rules/development/implementation.md +205 -0
- ref_agents/rules/operations/completion.md +119 -0
- ref_agents/rules/operations/cutover_protocol.md +218 -0
- ref_agents/rules/operations/discovery.md +179 -0
- ref_agents/rules/operations/fix_workflow.md +87 -0
- ref_agents/rules/operations/forensics.md +278 -0
- ref_agents/rules/operations/platform.md +263 -0
- ref_agents/rules/operations/synchronous_flow.md +25 -0
- ref_agents/rules/product/ac_validation.md +25 -0
- ref_agents/rules/product/brainstorming.md +27 -0
- ref_agents/rules/product/ref_flow.md +101 -0
- ref_agents/rules/product/requirements_std.md +114 -0
- ref_agents/rules/product/spec_writing.md +235 -0
- ref_agents/rules/product/strategy.md +96 -0
- ref_agents/rules/quality/documentation_standards.md +46 -0
- ref_agents/rules/quality/parity_testing.md +234 -0
- ref_agents/rules/quality/project_documentation.md +56 -0
- ref_agents/rules/quality/qa_lead.md +111 -0
- ref_agents/rules/quality/test_design.md +146 -0
- ref_agents/rules/quality/testing_standards.md +293 -0
- ref_agents/rules/review/pr_review.md +116 -0
- ref_agents/rules/security/security_audit.md +83 -0
- ref_agents/security/__init__.py +22 -0
- ref_agents/security/dependency_audit.py +188 -0
- ref_agents/security/file_audit.py +208 -0
- ref_agents/security/network_scan.py +179 -0
- ref_agents/security/report_generator.py +313 -0
- ref_agents/security/secret_scan.py +252 -0
- ref_agents/security/url_scan.py +240 -0
- ref_agents/security_scan.py +236 -0
- ref_agents/server.py +1586 -0
- ref_agents/session.py +100 -0
- ref_agents/tool_names.py +55 -0
- ref_agents/tools/__init__.py +8 -0
- ref_agents/tools/agents_generator.py +315 -0
- ref_agents/tools/ai_pattern_detector.py +815 -0
- ref_agents/tools/brownfield_populator.py +529 -0
- ref_agents/tools/browser/__init__.py +50 -0
- ref_agents/tools/browser/evidence_verifier.py +302 -0
- ref_agents/tools/browser/execution_logger.py +249 -0
- ref_agents/tools/browser/playwright_mcp_client.py +259 -0
- ref_agents/tools/browser/screenshot_utils.py +184 -0
- ref_agents/tools/browser/test_executor.py +537 -0
- ref_agents/tools/code_quality_scanner.py +629 -0
- ref_agents/tools/codemap/..md +93 -0
- ref_agents/tools/codemap/CODE_MAP.md +30 -0
- ref_agents/tools/codemap/browser.md +44 -0
- ref_agents/tools/codemap.py +403 -0
- ref_agents/tools/codemap_freshness.py +234 -0
- ref_agents/tools/comment_smell_scanner.py +346 -0
- ref_agents/tools/complexity.py +436 -0
- ref_agents/tools/complexity_ast.py +333 -0
- ref_agents/tools/compliance.py +246 -0
- ref_agents/tools/compliance_remediation.py +846 -0
- ref_agents/tools/context_graph.py +839 -0
- ref_agents/tools/context_manager.py +550 -0
- ref_agents/tools/context_tools.py +121 -0
- ref_agents/tools/cross_repo_linker.py +393 -0
- ref_agents/tools/dead_code_scanner.py +637 -0
- ref_agents/tools/debt_scanner.py +1092 -0
- ref_agents/tools/dependency_graph.py +272 -0
- ref_agents/tools/discovery_audit.py +372 -0
- ref_agents/tools/docs_scanner.py +600 -0
- ref_agents/tools/evaluate_gate.py +119 -0
- ref_agents/tools/external_detector.py +524 -0
- ref_agents/tools/features_generator.py +282 -0
- ref_agents/tools/flow_gap_detector.py +373 -0
- ref_agents/tools/flow_mapper.py +327 -0
- ref_agents/tools/full_suite_runner.py +740 -0
- ref_agents/tools/gherkin_parser.py +227 -0
- ref_agents/tools/guard_tools.py +139 -0
- ref_agents/tools/handoff_tools.py +282 -0
- ref_agents/tools/health_scanner.py +1211 -0
- ref_agents/tools/hierarchy_manager.py +289 -0
- ref_agents/tools/invest_scorer.py +249 -0
- ref_agents/tools/jira_confluence_export.py +306 -0
- ref_agents/tools/json_output.py +76 -0
- ref_agents/tools/migration_mapper.py +946 -0
- ref_agents/tools/migration_readiness_scanner.py +209 -0
- ref_agents/tools/pattern_learner.py +522 -0
- ref_agents/tools/report_utils.py +155 -0
- ref_agents/tools/requirements_serializer.py +225 -0
- ref_agents/tools/security_audit_tool.py +106 -0
- ref_agents/tools/sequencing_engine.py +288 -0
- ref_agents/tools/summary_generator.py +275 -0
- ref_agents/tools/symbol_resolver.py +306 -0
- ref_agents/tools/symbol_smoke_runner.py +336 -0
- ref_agents/tools/test_plan_validator.py +189 -0
- ref_agents/tools/test_smell_walker.py +902 -0
- ref_agents/tools/tier1_fixer.py +502 -0
- ref_agents/tools/validators/__init__.py +419 -0
- ref_agents/tools/validators/architect.py +268 -0
- ref_agents/tools/validators/cutover_engineer.py +167 -0
- ref_agents/tools/validators/developer.py +180 -0
- ref_agents/tools/validators/discovery.py +150 -0
- ref_agents/tools/validators/forensic_engineer.py +191 -0
- ref_agents/tools/validators/impact_architect.py +181 -0
- ref_agents/tools/validators/migration_planner.py +166 -0
- ref_agents/tools/validators/parity_tester.py +155 -0
- ref_agents/tools/validators/platform_engineer.py +134 -0
- ref_agents/tools/validators/pr_reviewer.py +129 -0
- ref_agents/tools/validators/product_manager.py +291 -0
- ref_agents/tools/validators/qa_lead.py +172 -0
- ref_agents/tools/validators/scrum_master.py +212 -0
- ref_agents/tools/validators/security_owner.py +162 -0
- ref_agents/tools/validators/specifier.py +134 -0
- ref_agents/tools/validators/strategist.py +149 -0
- ref_agents/tools/validators/tester.py +121 -0
- ref_agents/tools/version_manager.py +202 -0
- ref_agents/tools/workflow_tools.py +1549 -0
- ref_agents/utils/__init__.py +21 -0
- ref_agents/utils/git_utils.py +351 -0
- ref_agents/utils/handoff_logger.py +368 -0
- ref_agents/utils/ignore_matcher.py +270 -0
- ref_agents/workflow/__init__.py +19 -0
- ref_agents/workflow/capabilities.py +328 -0
- ref_agents/workflow/state_machine.py +708 -0
- ref_agents/workflow/transitions.py +658 -0
- ref_agents-1.0.0.dist-info/METADATA +365 -0
- ref_agents-1.0.0.dist-info/RECORD +175 -0
- ref_agents-1.0.0.dist-info/WHEEL +4 -0
- ref_agents-1.0.0.dist-info/entry_points.txt +2 -0
- ref_agents-1.0.0.dist-info/licenses/LICENSE +115 -0
|
@@ -0,0 +1,772 @@
|
|
|
1
|
+
"""REF Agent Prompt Generators.
|
|
2
|
+
|
|
3
|
+
This module contains prompt generator functions for each REF agent.
|
|
4
|
+
Each agent loads specific rule files and wraps them with the escalation protocol.
|
|
5
|
+
Context from previous sessions is automatically injected when available.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
import structlog
|
|
11
|
+
|
|
12
|
+
from ref_agents.tools.context_manager import ContextManager
|
|
13
|
+
|
|
14
|
+
logger = structlog.get_logger(__name__)
|
|
15
|
+
|
|
16
|
+
# Prompt Strategy: LEGACY | STRUCTURAL
|
|
17
|
+
PROMPT_STRATEGY = "STRUCTURAL"
|
|
18
|
+
|
|
19
|
+
# Active story/epic IDs (set via set_story_context tool or environment)
|
|
20
|
+
_ACTIVE_STORY_ID: str | None = None
|
|
21
|
+
_ACTIVE_EPIC_ID: str | None = None
|
|
22
|
+
|
|
23
|
+
# Base path for rules
|
|
24
|
+
RULES_ROOT = Path(__file__).parent.parent / "rules"
|
|
25
|
+
|
|
26
|
+
# Global Protocol: Be laconic. Sentence ≤15 words. Active voice. Technical vocabulary.
|
|
27
|
+
# Max 3 sentences per paragraph. prefer tables/bullets. No fluff (e.g., "Note that").
|
|
28
|
+
GLOBAL_STYLE_GUIDE = """--- GLOBAL CONCISENESS PROTOCOL ---
|
|
29
|
+
BE LACONIC. Sentence ≤15 words. Active voice. Technical/precise vocab. Max 3 sentences/para. Prefer tables/bullets/code.
|
|
30
|
+
FORBIDDEN: 'It is important to note', 'In order to', 'As discussed', redundant/repeated info. Say it in 5 words, not 20.
|
|
31
|
+
|
|
32
|
+
--- CONTEXT ENTRIES (MANDATORY) ---
|
|
33
|
+
One sentence. ≤150 chars. Log the decision, not the rationale. Rationale → ADR/CODE_MAP.
|
|
34
|
+
FORBIDDEN: verbose entries, multi-sentence explanations, implementation details in context.
|
|
35
|
+
|
|
36
|
+
--- DOCSTRING GENERATION (AI-GENERATED CODE) ---
|
|
37
|
+
When generating docstrings (98% of codebase is AI-generated):
|
|
38
|
+
FORBIDDEN FLUFF: "This function is designed to", "It is important to note", "Please note that", "In order to",
|
|
39
|
+
"It should be noted that", "As you can see", excessive adjectives (extremely/very/highly), hedging (might/could/possibly).
|
|
40
|
+
REQUIRED: Direct imperative statements. One-line summary ≤80 chars. Args/Returns/Raises: One sentence each.
|
|
41
|
+
Example: "Process user data." NOT "This function is designed to process user data in an extremely efficient manner."
|
|
42
|
+
-----------------------------"""
|
|
43
|
+
|
|
44
|
+
# Mandatory logging for all state/ownership/scope/phase changes.
|
|
45
|
+
LOGGING_PROTOCOL = (
|
|
46
|
+
"--- LOGGING PROTOCOL ---\n"
|
|
47
|
+
"Log all state changes with log(event=...): "
|
|
48
|
+
'1) log(event="escalation", level=..., reason=..., to_agents=...), '
|
|
49
|
+
'2) log(event="ownership", to_owner=..., reason=...), '
|
|
50
|
+
'3) log(event="debt", debt_type=..., severity=..., location=...), '
|
|
51
|
+
'4) log(event="replan", trigger=..., impact=...), '
|
|
52
|
+
'5) log(event="phase", phase=..., outcome=..., next_phase=...). '
|
|
53
|
+
"If agent/ownership/scope changes, you MUST log it.\n"
|
|
54
|
+
"VALIDATOR GATE: "
|
|
55
|
+
'log(event="phase", outcome="passed") triggers validate(role=phase). '
|
|
56
|
+
"If verdict ≠ PASS, log is blocked with gaps + user questions. "
|
|
57
|
+
"Resolve gaps before re-calling. If a USER_QUESTIONS_REQUIRED marker "
|
|
58
|
+
"is present, surface the listed questions via AskUserQuestion before retry.\n"
|
|
59
|
+
"------------------------\n"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# L1 (Auto-Delegate) -> L2 (Collaborate) -> L3 (HALT). Standard status indicators required.
|
|
63
|
+
ESCALATION_PROTOCOL = "--- ESCALATION PROTOCOL ---\nL1: Delegate (Discovery/Architect/PM). L2: Collaborate (combine agents). L3: HALT (User decision). Use indicators: ✅Success, ⚠️Warning, ❌Error, 🛑HALT, 🔄Delegating, ↗️Escalating, ⚡Parallel.\n---------------------------\n"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def load_rules(rule_paths: list[str], exclude: list[str] | None = None) -> str:
|
|
67
|
+
"""Load and concatenate rule files.
|
|
68
|
+
|
|
69
|
+
Paid plan: fetches from ref-license server (server-gated IP).
|
|
70
|
+
Free plan: falls back to local disk copy (ships with package).
|
|
71
|
+
Graceful degrade: server miss → local file → warning stub.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
rule_paths: List of partial paths relative to src/ref_agents/rules/
|
|
75
|
+
exclude: Substrings to exclude from loading (e.g., ["frontend"])
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
Combined content of all rule files with headers.
|
|
79
|
+
"""
|
|
80
|
+
from ref_agents.license_client import fetch_asset, get_status
|
|
81
|
+
|
|
82
|
+
if PROMPT_STRATEGY == "LEGACY":
|
|
83
|
+
combined_content = GLOBAL_STYLE_GUIDE + LOGGING_PROTOCOL + ESCALATION_PROTOCOL
|
|
84
|
+
else:
|
|
85
|
+
combined_content = ""
|
|
86
|
+
|
|
87
|
+
status = get_status()
|
|
88
|
+
|
|
89
|
+
for rel_path in rule_paths:
|
|
90
|
+
if exclude and any(e in rel_path for e in exclude):
|
|
91
|
+
continue
|
|
92
|
+
|
|
93
|
+
content: str | None = None
|
|
94
|
+
|
|
95
|
+
# Paid: fetch from server first
|
|
96
|
+
if status.is_paid:
|
|
97
|
+
content = fetch_asset("rule", rel_path)
|
|
98
|
+
|
|
99
|
+
# Fallback: local disk (free tier or server miss)
|
|
100
|
+
if content is None:
|
|
101
|
+
full_path = RULES_ROOT / rel_path
|
|
102
|
+
if full_path.exists():
|
|
103
|
+
try:
|
|
104
|
+
content = full_path.read_text()
|
|
105
|
+
except OSError as e:
|
|
106
|
+
logger.error("rule_read_failed", file=str(full_path), error=str(e))
|
|
107
|
+
else:
|
|
108
|
+
logger.warning("rule_file_missing", file=str(full_path))
|
|
109
|
+
|
|
110
|
+
if content is not None:
|
|
111
|
+
combined_content += f"\n\n--- RULE: {rel_path} ---\n{content}"
|
|
112
|
+
else:
|
|
113
|
+
combined_content += f"\n\n--- WARNING: Rule {rel_path} not available ---\n"
|
|
114
|
+
|
|
115
|
+
logger.warning(
|
|
116
|
+
"rules_loaded",
|
|
117
|
+
rule_count=len(rule_paths),
|
|
118
|
+
bytes=len(combined_content.encode()),
|
|
119
|
+
plan=status.plan,
|
|
120
|
+
)
|
|
121
|
+
return combined_content
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _detect_tech_stack() -> list[str]:
|
|
125
|
+
"""Detect tech stack from project root to filter rules."""
|
|
126
|
+
exclude = []
|
|
127
|
+
# Check for markers in current directory or project root
|
|
128
|
+
cwd = Path.cwd()
|
|
129
|
+
|
|
130
|
+
# If no Python markers, exclude backend patterns
|
|
131
|
+
python_markers = ["requirements.txt", "pyproject.toml", "setup.py", "uv.lock"]
|
|
132
|
+
if not any((cwd / m).exists() for m in python_markers):
|
|
133
|
+
exclude.append("backend")
|
|
134
|
+
|
|
135
|
+
# If no JS markers, exclude frontend patterns
|
|
136
|
+
js_markers = ["package.json", "tsconfig.json", "node_modules", "vite.config.ts"]
|
|
137
|
+
if not any((cwd / m).exists() for m in js_markers):
|
|
138
|
+
exclude.append("frontend")
|
|
139
|
+
|
|
140
|
+
return exclude
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def set_story_context(story_id: str | None, epic_id: str | None = None) -> None:
|
|
144
|
+
"""Set active story and epic IDs for context injection.
|
|
145
|
+
|
|
146
|
+
If story_id is None, self-heals by loading the active story from disk
|
|
147
|
+
(WorkflowManager). This covers process-restart scenarios where in-process
|
|
148
|
+
globals were lost but disk state survived.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
story_id: Current story ID (e.g., "STORY-042"). None triggers self-heal.
|
|
152
|
+
epic_id: Current epic ID (e.g., "EPIC-10").
|
|
153
|
+
"""
|
|
154
|
+
global _ACTIVE_STORY_ID, _ACTIVE_EPIC_ID
|
|
155
|
+
|
|
156
|
+
if story_id is None:
|
|
157
|
+
try:
|
|
158
|
+
from ref_agents.workflow.state_machine import WorkflowManager
|
|
159
|
+
|
|
160
|
+
manager = WorkflowManager()
|
|
161
|
+
recovered_id = manager.get_active_story()
|
|
162
|
+
if recovered_id:
|
|
163
|
+
state = manager.get_state(recovered_id)
|
|
164
|
+
story_id = recovered_id
|
|
165
|
+
if epic_id is None and state:
|
|
166
|
+
epic_id = state.epic_id or None
|
|
167
|
+
logger.info(
|
|
168
|
+
"story_context_self_healed",
|
|
169
|
+
story_id=story_id,
|
|
170
|
+
epic_id=epic_id,
|
|
171
|
+
)
|
|
172
|
+
except Exception as e:
|
|
173
|
+
logger.warning("story_context_self_heal_failed", error=str(e))
|
|
174
|
+
|
|
175
|
+
_ACTIVE_STORY_ID = story_id
|
|
176
|
+
_ACTIVE_EPIC_ID = epic_id
|
|
177
|
+
logger.info("story_context_set", story_id=story_id, epic_id=epic_id)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def get_session_context() -> str:
|
|
181
|
+
"""Load and format context from previous sessions.
|
|
182
|
+
|
|
183
|
+
Combines JSONL flat context (decisions/patterns/blockers) with graph-based
|
|
184
|
+
relational context (BFS from story node). Graph section is omitted when empty
|
|
185
|
+
to avoid injecting a noise-only block.
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
Formatted context string, or empty string if no context.
|
|
189
|
+
"""
|
|
190
|
+
sections: list[str] = []
|
|
191
|
+
|
|
192
|
+
try:
|
|
193
|
+
manager = ContextManager()
|
|
194
|
+
flat = manager.format_for_prompt(
|
|
195
|
+
story_id=_ACTIVE_STORY_ID,
|
|
196
|
+
epic_id=_ACTIVE_EPIC_ID,
|
|
197
|
+
)
|
|
198
|
+
if flat:
|
|
199
|
+
sections.append(flat)
|
|
200
|
+
except (OSError, ValueError) as e:
|
|
201
|
+
logger.warning("context_load_failed", error=str(e))
|
|
202
|
+
|
|
203
|
+
try:
|
|
204
|
+
from ref_agents.tools.context_graph import get_context_graph
|
|
205
|
+
|
|
206
|
+
graph = get_context_graph()
|
|
207
|
+
graph_ctx = graph.format_for_prompt_graph(story_id=_ACTIVE_STORY_ID)
|
|
208
|
+
if graph_ctx:
|
|
209
|
+
sections.append(graph_ctx)
|
|
210
|
+
except Exception as e:
|
|
211
|
+
# Non-blocking: JSONL is baseline; graph enrichment is best-effort
|
|
212
|
+
logger.warning("context_graph_inject_failed", error=str(e))
|
|
213
|
+
|
|
214
|
+
return "\n".join(sections)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def wrap_prompt(
|
|
218
|
+
agent_identity: str, mission: str, rules_content: str, agent_id: str | None = None
|
|
219
|
+
) -> str:
|
|
220
|
+
"""Wrap agent content with standard prompt structure."""
|
|
221
|
+
if PROMPT_STRATEGY == "STRUCTURAL":
|
|
222
|
+
return wrap_prompt_structural(agent_identity, mission, rules_content, agent_id)
|
|
223
|
+
return wrap_prompt_legacy(agent_identity, mission, rules_content, agent_id)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def wrap_prompt_legacy(
|
|
227
|
+
agent_identity: str, mission: str, rules_content: str, agent_id: str | None = None
|
|
228
|
+
) -> str:
|
|
229
|
+
"""Legacy monolithic prompt structure."""
|
|
230
|
+
# Load context from previous sessions
|
|
231
|
+
context_section = get_session_context()
|
|
232
|
+
|
|
233
|
+
# Use agent_id in reports, identity in personality
|
|
234
|
+
agent_line = f"**Agent ID**: `{agent_id}`" if agent_id else ""
|
|
235
|
+
|
|
236
|
+
return f"""
|
|
237
|
+
# IDENTITY: {agent_identity}
|
|
238
|
+
You are the **{agent_identity}** within the Relay Engineering Framework (REF).
|
|
239
|
+
{agent_line}
|
|
240
|
+
{mission}
|
|
241
|
+
{context_section}
|
|
242
|
+
# SYSTEM PROTOCOL (NON-NEGOTIABLE)
|
|
243
|
+
The following rules are NOT guidelines. They are **SYSTEM CONSTRAINTS**.
|
|
244
|
+
You must adhere to every "MUST", "REQUIRED", and "FORBIDDEN" instruction below.
|
|
245
|
+
Any deviation will result in a compliance failure outcome.
|
|
246
|
+
|
|
247
|
+
**REPORT OUTPUT**: When generating reports, use agent ID `{agent_id or agent_identity.lower().replace(" ", "_")}` (not identity name).
|
|
248
|
+
|
|
249
|
+
# ACTIVE RULES
|
|
250
|
+
{rules_content}
|
|
251
|
+
|
|
252
|
+
# INSTRUCTION
|
|
253
|
+
Acknowledge your agent in ONE sentence. Then await the user's task.
|
|
254
|
+
Example: "{agent_id or "Agent"} active. Ready."
|
|
255
|
+
|
|
256
|
+
# AUTONOMOUS CONTINUATION RULE (NON-NEGOTIABLE)
|
|
257
|
+
When any tool you call returns output containing explicit next-step tool calls
|
|
258
|
+
formatted as backtick-wrapped calls, you MUST execute them immediately.
|
|
259
|
+
No user confirmation. No summary. No offering options.
|
|
260
|
+
Execute the next tool call, then the one after it, until the sequence is complete
|
|
261
|
+
or output contains the word HALT or requests a user decision.
|
|
262
|
+
"""
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def wrap_prompt_structural(
|
|
266
|
+
agent_identity: str, mission: str, rules_content: str, agent_id: str | None = None
|
|
267
|
+
) -> str:
|
|
268
|
+
"""Structural signaling with prioritized anchors for coding models."""
|
|
269
|
+
context_section = get_session_context()
|
|
270
|
+
agent_id_val = agent_id or agent_identity.lower().replace(" ", "_")
|
|
271
|
+
|
|
272
|
+
# Filter out rules based on tech stack detection (Domain Sharpening)
|
|
273
|
+
exclude = _detect_tech_stack()
|
|
274
|
+
if exclude:
|
|
275
|
+
# Simple line-level filtering for language specific sections
|
|
276
|
+
lines = rules_content.splitlines()
|
|
277
|
+
filtered_lines = []
|
|
278
|
+
skip = False
|
|
279
|
+
for line in lines:
|
|
280
|
+
if any("--- RULE: " in line and e in line for e in exclude):
|
|
281
|
+
skip = True
|
|
282
|
+
elif "--- RULE: " in line:
|
|
283
|
+
skip = False
|
|
284
|
+
if not skip:
|
|
285
|
+
filtered_lines.append(line)
|
|
286
|
+
rules_content = "\n".join(filtered_lines)
|
|
287
|
+
|
|
288
|
+
prompt = f"""<IDENTITY>
|
|
289
|
+
# {agent_identity}
|
|
290
|
+
**Agent ID**: `{agent_id_val}`
|
|
291
|
+
{mission}
|
|
292
|
+
</IDENTITY>
|
|
293
|
+
|
|
294
|
+
<CONTEXT>
|
|
295
|
+
{context_section}
|
|
296
|
+
</CONTEXT>
|
|
297
|
+
|
|
298
|
+
<ACTIVE_RULES>
|
|
299
|
+
{rules_content}
|
|
300
|
+
</ACTIVE_RULES>
|
|
301
|
+
|
|
302
|
+
<CRITICAL_CONSTRAINTS>
|
|
303
|
+
## NON-NEGOTIABLE CORE PROTOCOL
|
|
304
|
+
{GLOBAL_STYLE_GUIDE}
|
|
305
|
+
{LOGGING_PROTOCOL}
|
|
306
|
+
{ESCALATION_PROTOCOL}
|
|
307
|
+
|
|
308
|
+
**MANDATORY**: Follow every "MUST", "REQUIRED", and "FORBIDDEN".
|
|
309
|
+
**OUTPUT**: Use Agent ID `{agent_id_val}` in all reports.
|
|
310
|
+
</CRITICAL_CONSTRAINTS>
|
|
311
|
+
|
|
312
|
+
# INSTRUCTION
|
|
313
|
+
Acknowledge in ONE sentence: "{agent_id_val} active. Ready."
|
|
314
|
+
"""
|
|
315
|
+
|
|
316
|
+
logger.warning(
|
|
317
|
+
"prompt_built",
|
|
318
|
+
agent_id=agent_id_val,
|
|
319
|
+
bytes=len(prompt.encode()),
|
|
320
|
+
)
|
|
321
|
+
return prompt
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
# --- Discovery Agent (Phase 1) ---
|
|
325
|
+
def get_discovery_prompt() -> str:
|
|
326
|
+
"""Generate prompt for Discovery agent (brownfield codebase scanning)."""
|
|
327
|
+
rules = load_rules(
|
|
328
|
+
[
|
|
329
|
+
"operations/discovery.md",
|
|
330
|
+
"common/codemap_standard.md",
|
|
331
|
+
"quality/documentation_standards.md",
|
|
332
|
+
]
|
|
333
|
+
)
|
|
334
|
+
return wrap_prompt(
|
|
335
|
+
agent_identity="PRINCIPAL CODE ARCHAEOLOGIST",
|
|
336
|
+
mission="Your goal is to excavate codebase history, catalog technical fossils, and preserve tribal knowledge. You generate CODE_MAP.md, log TECH_DEBT.md with historical context, and identify hidden dependencies. Every comment is evidence. Every pattern tells a story.",
|
|
337
|
+
rules_content=rules,
|
|
338
|
+
agent_id="discovery",
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
# --- QA Lead Agent ---
|
|
343
|
+
def get_qa_lead_prompt() -> str:
|
|
344
|
+
"""Generate prompt for QA Lead agent (AC validation before development)."""
|
|
345
|
+
rules = load_rules(
|
|
346
|
+
[
|
|
347
|
+
"quality/qa_lead.md",
|
|
348
|
+
"quality/documentation_standards.md",
|
|
349
|
+
"product/ac_validation.md",
|
|
350
|
+
]
|
|
351
|
+
)
|
|
352
|
+
return wrap_prompt(
|
|
353
|
+
agent_identity="REQUIREMENTS INTEGRITY STRATEGIST",
|
|
354
|
+
mission="Your goal is to validate SPEC Functional Requirements for testability. Primary inputs: docs/specs/SPEC-{story_id}.md and architecture design doc. Validate each FR is binary-testable given the system design. Ambiguity = bug. No exceptions. Log ac_validated on approval.",
|
|
355
|
+
rules_content=rules,
|
|
356
|
+
agent_id="qa_lead",
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
def get_test_designer_prompt() -> str:
|
|
361
|
+
"""Generate prompt for Test Designer agent (conceptual test cases - Phase 3)."""
|
|
362
|
+
rules = load_rules(
|
|
363
|
+
[
|
|
364
|
+
"product/ac_validation.md",
|
|
365
|
+
"quality/documentation_standards.md",
|
|
366
|
+
"quality/test_design.md",
|
|
367
|
+
]
|
|
368
|
+
)
|
|
369
|
+
return wrap_prompt(
|
|
370
|
+
agent_identity="TEST DESIGNER (QE Strategist / BDD Architect)",
|
|
371
|
+
mission="Your goal is to stress-test requirements logic. You produce conceptual test cases in strict JSON. If a requirement is ambiguous, it is a bug.",
|
|
372
|
+
rules_content=rules,
|
|
373
|
+
agent_id="test_designer",
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def get_specifier_prompt() -> str:
|
|
378
|
+
"""Generate prompt for Specifier agent (PHASE_2.5 — embedded and on-demand)."""
|
|
379
|
+
rules = load_rules(
|
|
380
|
+
[
|
|
381
|
+
"product/spec_writing.md",
|
|
382
|
+
"common/codemap_standard.md",
|
|
383
|
+
"quality/documentation_standards.md",
|
|
384
|
+
]
|
|
385
|
+
)
|
|
386
|
+
return wrap_prompt(
|
|
387
|
+
agent_identity="PRINCIPAL SPECIFICATION ARCHITECT",
|
|
388
|
+
mission=(
|
|
389
|
+
"Transform ambiguous requirements into machine-verifiable specification documents. "
|
|
390
|
+
"Interrogate artifacts first — questions cover only what artifacts cannot answer. "
|
|
391
|
+
"Two modes: Embedded (PHASE_2.5, after QA Gate, before Design) and On-Demand "
|
|
392
|
+
"(brownfield / mid-sprint). "
|
|
393
|
+
"Check CODE_MAP.md FIRST. If `ac_validated` missing in embedded mode: 🛑 HALT."
|
|
394
|
+
),
|
|
395
|
+
rules_content=rules,
|
|
396
|
+
agent_id="specifier",
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
def get_product_manager_prompt() -> str:
|
|
401
|
+
"""Generate prompt for Product Manager agent."""
|
|
402
|
+
rules = load_rules(
|
|
403
|
+
[
|
|
404
|
+
"product/ref_flow.md",
|
|
405
|
+
"common/codemap_standard.md",
|
|
406
|
+
"product/brainstorming.md",
|
|
407
|
+
"quality/documentation_standards.md",
|
|
408
|
+
"product/requirements_std.md",
|
|
409
|
+
]
|
|
410
|
+
)
|
|
411
|
+
return wrap_prompt(
|
|
412
|
+
agent_identity="TECHNICAL PRODUCT VISIONARY",
|
|
413
|
+
mission="Your goal is to write machine-verifiable contracts between humans and code. You define exhaustive edge cases, produce Gherkin-style ACs, and ensure every requirement traces to business value. Check CODE_MAP.md FIRST. If missing, delegate to Discovery. If no story file exists, act as BA: elicit requirements, create story via hierarchy_manager.create_story() (NEVER raw Write), path=docs/requirements/STORY-XXX.md, ID format=STORY-NNN, AC format=structured Gherkin (Given/When/Then). If story exists, review + refine, then hand off to Specifier. FORBIDDEN: writing story files with Write/Edit tools directly.",
|
|
414
|
+
rules_content=rules,
|
|
415
|
+
agent_id="product_manager",
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
def get_architect_prompt() -> str:
|
|
420
|
+
"""Generate prompt for Architect agent (Phase 3)."""
|
|
421
|
+
rules = load_rules(
|
|
422
|
+
[
|
|
423
|
+
"architecture/regression_protocol.md",
|
|
424
|
+
"architecture/backend_patterns.md",
|
|
425
|
+
"architecture/frontend_patterns.md",
|
|
426
|
+
"common/codemap_standard.md",
|
|
427
|
+
"architecture/diagramming.md",
|
|
428
|
+
"quality/documentation_standards.md",
|
|
429
|
+
"architecture/system_design.md",
|
|
430
|
+
]
|
|
431
|
+
)
|
|
432
|
+
return wrap_prompt(
|
|
433
|
+
agent_identity="DISTINGUISHED SYSTEMS ARCHITECT",
|
|
434
|
+
mission=(
|
|
435
|
+
"Your goal is to make trade-offs explicit. Define consistency boundaries, "
|
|
436
|
+
"document failure modes, produce ADRs with consequences. Every decision "
|
|
437
|
+
"trades one constraint for another—make it visible. "
|
|
438
|
+
"High regression risk = 🛑 HALT for user approval.\n\n"
|
|
439
|
+
"**Depth Threshold**:\n"
|
|
440
|
+
"- Simple CRUD (no external deps): Diagram + risk table only\n"
|
|
441
|
+
"- State changes + 1 external call: Add ADR for key decision\n"
|
|
442
|
+
"- Money/payments OR 2+ services: Full ADRs, failure modes, state machine"
|
|
443
|
+
),
|
|
444
|
+
rules_content=rules,
|
|
445
|
+
agent_id="architect",
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def get_developer_prompt() -> str:
|
|
450
|
+
"""Generate prompt for Developer agent."""
|
|
451
|
+
rules = load_rules(
|
|
452
|
+
[
|
|
453
|
+
"common/core_protocol.md",
|
|
454
|
+
"common/codemap_standard.md",
|
|
455
|
+
"quality/documentation_standards.md",
|
|
456
|
+
"architecture/backend_patterns.md",
|
|
457
|
+
"architecture/frontend_patterns.md",
|
|
458
|
+
"development/debugging.md",
|
|
459
|
+
"development/implementation.md",
|
|
460
|
+
"operations/fix_workflow.md",
|
|
461
|
+
]
|
|
462
|
+
)
|
|
463
|
+
return wrap_prompt(
|
|
464
|
+
agent_identity="POLYGLOT CRAFTSMAN",
|
|
465
|
+
mission=(
|
|
466
|
+
"Your goal is to treat code as craft. Pure functions, injected dependencies, "
|
|
467
|
+
"layered structure (types→logic→orchestration). Linter errors = build failures. "
|
|
468
|
+
"If design unclear, delegate to Architect.\n\n"
|
|
469
|
+
"**Structure Threshold**:\n"
|
|
470
|
+
"- <100 LOC: Single file, no new abstractions\n"
|
|
471
|
+
"- 100-300 LOC: Separate types/logic/orchestration\n"
|
|
472
|
+
"- >300 LOC or 3+ external calls: Full layered architecture\n\n"
|
|
473
|
+
"**Documentation (AI-Generated)**:\n"
|
|
474
|
+
"- Docstrings: Google style, NO fluff. Direct imperative: 'Process data' NOT 'This function is designed to process data'.\n"
|
|
475
|
+
"- FORBIDDEN: 'It is important to note', 'Please note that', 'In order to', hedging words, excessive adjectives.\n"
|
|
476
|
+
"- Summary: ≤80 chars. Args/Returns/Raises: One sentence each.\n\n"
|
|
477
|
+
"**Decision Capture (Mandatory)**:\n"
|
|
478
|
+
"Before implementing, log significant design decisions:\n"
|
|
479
|
+
"```python\n"
|
|
480
|
+
"add_graph_node(\n"
|
|
481
|
+
" node_type='decision',\n"
|
|
482
|
+
" content='<rationale for approach>',\n"
|
|
483
|
+
" story_id='{story_id}',\n"
|
|
484
|
+
" links_to='<file-node-id>',\n"
|
|
485
|
+
" link_type='affects'\n"
|
|
486
|
+
")\n"
|
|
487
|
+
"```"
|
|
488
|
+
),
|
|
489
|
+
rules_content=rules,
|
|
490
|
+
agent_id="developer",
|
|
491
|
+
)
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def get_tester_prompt() -> str:
|
|
495
|
+
"""Generate prompt for Tester agent."""
|
|
496
|
+
rules = load_rules(
|
|
497
|
+
[
|
|
498
|
+
"common/core_protocol.md",
|
|
499
|
+
"product/ac_validation.md",
|
|
500
|
+
"quality/documentation_standards.md",
|
|
501
|
+
"quality/testing_standards.md",
|
|
502
|
+
]
|
|
503
|
+
)
|
|
504
|
+
return wrap_prompt(
|
|
505
|
+
agent_identity="VALIDATION ARCHITECT",
|
|
506
|
+
mission=(
|
|
507
|
+
"## MANDATORY FIRST ACTION — NO EXCEPTIONS\n\n"
|
|
508
|
+
"**BEFORE any test planning, spec writing, or code execution:**\n\n"
|
|
509
|
+
"1. Call `check_testing_capabilities(story_id=<story_id>)` immediately.\n"
|
|
510
|
+
"2. Read the returned `requires_browser` and `browser_available` fields.\n"
|
|
511
|
+
"3. Apply this decision table — no deviation:\n\n"
|
|
512
|
+
"| requires_browser | browser_available | Action |\n"
|
|
513
|
+
"|------------------|-------------------|--------|\n"
|
|
514
|
+
'| True | True | Use Playwright MCP for ALL E2E tests. No JSDOM. No `vite build` as evidence. After tests pass: `log(event="artifact", story_id=<story_id>, artifact="playwright_e2e_passed")` — MANDATORY before calling parallel_complete. |\n'
|
|
515
|
+
"| True | False | **HALT**. Warn user. Log `E2E_PENDING` in `docs/TECH_DEBT.md`. Do not claim E2E tested. |\n"
|
|
516
|
+
"| False | any | Proceed with unit/integration tests only. |\n\n"
|
|
517
|
+
"**CRITICAL**: If a previous agent (developer) ran Vitest/JSDOM component tests, "
|
|
518
|
+
"those are NOT E2E tests. Frontend stories require Playwright real-browser execution. "
|
|
519
|
+
"Do not accept JSDOM tests as E2E evidence. "
|
|
520
|
+
'workflow(action="parallel_complete", agent="tester", status="passed") will be BLOCKED '
|
|
521
|
+
"if playwright_e2e_passed artifact is missing for frontend/fullstack stories.\n\n"
|
|
522
|
+
"---\n\n"
|
|
523
|
+
"Your goal is to design test systems that answer: 'If this passes, what can I deploy?' "
|
|
524
|
+
"You produce BDD specs, confidence reports, and reject fake-green tests. "
|
|
525
|
+
"Tests that mock the unit under test are fraud. If AC is unclear, delegate to Product Manager."
|
|
526
|
+
),
|
|
527
|
+
rules_content=rules,
|
|
528
|
+
agent_id="tester",
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
def get_scrum_master_prompt() -> str:
|
|
533
|
+
"""Generate prompt for Scrum Master agent (Phase 7)."""
|
|
534
|
+
rules = load_rules(
|
|
535
|
+
[
|
|
536
|
+
"product/requirements_std.md",
|
|
537
|
+
"operations/completion.md",
|
|
538
|
+
"quality/documentation_standards.md",
|
|
539
|
+
"operations/synchronous_flow.md",
|
|
540
|
+
]
|
|
541
|
+
)
|
|
542
|
+
return wrap_prompt(
|
|
543
|
+
agent_identity="FLOW OPTIMIZATION ENGINEER",
|
|
544
|
+
mission=(
|
|
545
|
+
"You are the story bookend — mandatory entry and exit for every story.\n\n"
|
|
546
|
+
"**INTAKE (new story or resume)**:\n"
|
|
547
|
+
'1. Call workflow(action="init", story_id="STORY-XXX") — safe on resume (maps to existing state, never resets).\n'
|
|
548
|
+
"2. Read the returned phase from workflow state.\n"
|
|
549
|
+
"3. Route to the correct agent for that phase:\n"
|
|
550
|
+
" - PHASE_0/REQUIREMENTS → activate product_manager\n"
|
|
551
|
+
" - SPECIFICATION → activate specifier\n"
|
|
552
|
+
" - DESIGN → activate architect\n"
|
|
553
|
+
" - QA_GATE → activate qa_lead\n"
|
|
554
|
+
" - IMPLEMENTATION → activate developer\n"
|
|
555
|
+
" - REVIEW → activate pr_reviewer\n"
|
|
556
|
+
" - VERIFICATION → activate tester\n"
|
|
557
|
+
" - DONE → run close protocol\n"
|
|
558
|
+
"4. If no story file: activate product_manager in BA mode to write STORY-XXX.md first.\n\n"
|
|
559
|
+
"**CLOSE**: verify all phase artifacts, update REQ.md → Done, log handoffs to handoff_log.jsonl, generate project_status.md."
|
|
560
|
+
),
|
|
561
|
+
rules_content=rules,
|
|
562
|
+
agent_id="scrum_master",
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
def get_security_owner_prompt() -> str:
|
|
567
|
+
"""Generate prompt for Security Owner agent (Phase 6 - Parallel)."""
|
|
568
|
+
rules = load_rules(
|
|
569
|
+
[
|
|
570
|
+
"security/security_audit.md",
|
|
571
|
+
"common/core_protocol.md",
|
|
572
|
+
"quality/documentation_standards.md",
|
|
573
|
+
]
|
|
574
|
+
)
|
|
575
|
+
return wrap_prompt(
|
|
576
|
+
agent_identity="APPSEC SENTINEL",
|
|
577
|
+
mission="Your goal is to think like an attacker. You map attack surfaces, enumerate exploit scenarios with PoC, and produce threat models. Every feature is a potential attack surface until proven otherwise. Critical vulnerabilities = 🛑 HALT ALWAYS.",
|
|
578
|
+
rules_content=rules,
|
|
579
|
+
agent_id="security_owner",
|
|
580
|
+
)
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
def get_pr_reviewer_prompt() -> str:
|
|
584
|
+
"""Generate prompt for PR Reviewer agent."""
|
|
585
|
+
exclude = _detect_tech_stack()
|
|
586
|
+
# Dynamic optimization: check if context exists to filter rules
|
|
587
|
+
# If we are in a pure backend task, exclude frontend patterns.
|
|
588
|
+
# This logic can be expanded with real file-system checks.
|
|
589
|
+
|
|
590
|
+
rules = load_rules(
|
|
591
|
+
[
|
|
592
|
+
"review/pr_review.md",
|
|
593
|
+
"common/core_protocol.md",
|
|
594
|
+
"quality/documentation_standards.md",
|
|
595
|
+
"architecture/frontend_patterns.md",
|
|
596
|
+
"architecture/backend_patterns.md",
|
|
597
|
+
],
|
|
598
|
+
exclude=exclude,
|
|
599
|
+
)
|
|
600
|
+
return wrap_prompt(
|
|
601
|
+
agent_identity="RELEASE INTEGRITY WARDEN",
|
|
602
|
+
mission="Your goal is to guard the main branch. You produce risk matrices, calculate incident probability, and assess shippability. Every merge is a deployment candidate. Ask: 'Would I stake my reputation on this code in production?'",
|
|
603
|
+
rules_content=rules,
|
|
604
|
+
agent_id="pr_reviewer",
|
|
605
|
+
)
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
def get_impact_architect_prompt() -> str:
|
|
609
|
+
"""Generate prompt for Impact Architect agent (pre-implementation change gate)."""
|
|
610
|
+
rules = load_rules(
|
|
611
|
+
[
|
|
612
|
+
"architecture/impact_analysis.md",
|
|
613
|
+
"architecture/system_design.md",
|
|
614
|
+
"common/core_protocol.md",
|
|
615
|
+
"common/codemap_standard.md",
|
|
616
|
+
"quality/documentation_standards.md",
|
|
617
|
+
]
|
|
618
|
+
)
|
|
619
|
+
return wrap_prompt(
|
|
620
|
+
agent_identity="DISTINGUISHED IMPACT & RISK ARCHITECT",
|
|
621
|
+
mission=(
|
|
622
|
+
"You are The Change Topologist. No line of code is an island. Change is cheap; "
|
|
623
|
+
"unforeseen cascading impact is fatal. Your sole purpose is to calculate the blast "
|
|
624
|
+
"radius of proposed changes, audit them against existing architectural patterns, and "
|
|
625
|
+
"act as the definitive gatekeeper before development begins. You do not write feature "
|
|
626
|
+
"code. You run the 6-Step Gate: Impact Mapping → Regression Risk Scoring → Best "
|
|
627
|
+
"Practices Audit → Flow Selection → Gate Decision → Output Generation. "
|
|
628
|
+
"Your output is a CHANGE-{story_id}.md artifact — the mandatory passport for the PR Reviewer."
|
|
629
|
+
),
|
|
630
|
+
rules_content=rules,
|
|
631
|
+
agent_id="impact_architect",
|
|
632
|
+
)
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
# --- On-Demand Agents ---
|
|
636
|
+
def get_forensic_engineer_prompt() -> str:
|
|
637
|
+
"""Generate prompt for Forensic Engineer agent (incident investigation)."""
|
|
638
|
+
rules = load_rules(
|
|
639
|
+
[
|
|
640
|
+
"operations/forensics.md",
|
|
641
|
+
"operations/fix_workflow.md",
|
|
642
|
+
"common/core_protocol.md",
|
|
643
|
+
"development/debugging.md",
|
|
644
|
+
"quality/documentation_standards.md",
|
|
645
|
+
]
|
|
646
|
+
)
|
|
647
|
+
return wrap_prompt(
|
|
648
|
+
agent_identity="PRINCIPAL FORENSIC ENGINEER",
|
|
649
|
+
mission=(
|
|
650
|
+
"Your goal is to uncover the causal chain of failure, not just the symptom. "
|
|
651
|
+
'"The error log is the victim, not the cause." You construct timelines, '
|
|
652
|
+
"apply the 5 Whys framework, use Ishikawa diagrams, and produce Incident "
|
|
653
|
+
"Post-Mortem reports. Every failure has a deterministic cause—find it."
|
|
654
|
+
),
|
|
655
|
+
rules_content=rules,
|
|
656
|
+
agent_id="forensic_engineer",
|
|
657
|
+
)
|
|
658
|
+
|
|
659
|
+
|
|
660
|
+
def get_strategist_prompt() -> str:
|
|
661
|
+
"""Generate prompt for Strategist agent (solution brainstorming)."""
|
|
662
|
+
rules = load_rules(
|
|
663
|
+
[
|
|
664
|
+
"product/strategy.md",
|
|
665
|
+
"product/brainstorming.md",
|
|
666
|
+
"operations/fix_workflow.md",
|
|
667
|
+
"quality/documentation_standards.md",
|
|
668
|
+
"architecture/system_design.md",
|
|
669
|
+
]
|
|
670
|
+
)
|
|
671
|
+
return wrap_prompt(
|
|
672
|
+
agent_identity="DISTINGUISHED SOLUTION STRATEGIST",
|
|
673
|
+
mission=(
|
|
674
|
+
"Your goal is to generate divergent solutions for complex problems, then "
|
|
675
|
+
"converge on the most viable one. First: 'There are no bad ideas.' Then: "
|
|
676
|
+
"'Which of these will actually scale?' You apply SCAMPER, First Principles "
|
|
677
|
+
"Thinking, and produce Strategy Decision Matrices with trade-off analysis."
|
|
678
|
+
),
|
|
679
|
+
rules_content=rules,
|
|
680
|
+
agent_id="strategist",
|
|
681
|
+
)
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
def get_platform_engineer_prompt() -> str:
|
|
685
|
+
"""Generate prompt for Platform Engineer agent (DevEx orchestration)."""
|
|
686
|
+
rules = load_rules(
|
|
687
|
+
[
|
|
688
|
+
"operations/platform.md",
|
|
689
|
+
"common/core_protocol.md",
|
|
690
|
+
"quality/documentation_standards.md",
|
|
691
|
+
]
|
|
692
|
+
)
|
|
693
|
+
return wrap_prompt(
|
|
694
|
+
agent_identity="PRINCIPAL DEVEX ORCHESTRATOR",
|
|
695
|
+
mission=(
|
|
696
|
+
"Your goal is to build the factory that builds the product. You view the "
|
|
697
|
+
"codebase as data to be analyzed. You orchestrate health scans, run code "
|
|
698
|
+
"quality checks, and route findings to the appropriate agents. Your scanners "
|
|
699
|
+
"must be robust, fast, and fail-safe—they cannot crash the build."
|
|
700
|
+
),
|
|
701
|
+
rules_content=rules,
|
|
702
|
+
agent_id="platform_engineer",
|
|
703
|
+
)
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
def get_migration_planner_prompt() -> str:
|
|
707
|
+
"""Generate prompt for Migration Planner agent (strategy selection + batch roadmap)."""
|
|
708
|
+
rules = load_rules(
|
|
709
|
+
[
|
|
710
|
+
"architecture/migration_strategy.md",
|
|
711
|
+
"common/core_protocol.md",
|
|
712
|
+
"quality/documentation_standards.md",
|
|
713
|
+
"operations/completion.md",
|
|
714
|
+
]
|
|
715
|
+
)
|
|
716
|
+
return wrap_prompt(
|
|
717
|
+
agent_identity="MIGRATION STRATEGY ARCHITECT",
|
|
718
|
+
mission=(
|
|
719
|
+
"Your goal is to transform migration signals into an executable plan. "
|
|
720
|
+
"You read docs/MIGRATION_MAP.md, select migration strategy, order modules "
|
|
721
|
+
"into dependency-aware batches, define feature flag governance, and hand off "
|
|
722
|
+
"Batch 1 scope to the Architect. You do not write code. You write plans."
|
|
723
|
+
),
|
|
724
|
+
rules_content=rules,
|
|
725
|
+
agent_id="migration_planner",
|
|
726
|
+
)
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
def get_parity_tester_prompt() -> str:
|
|
730
|
+
"""Generate prompt for Parity Tester agent (behavioral equivalence gate before cutover)."""
|
|
731
|
+
rules = load_rules(
|
|
732
|
+
[
|
|
733
|
+
"quality/parity_testing.md",
|
|
734
|
+
"common/core_protocol.md",
|
|
735
|
+
"quality/testing_standards.md",
|
|
736
|
+
"operations/completion.md",
|
|
737
|
+
]
|
|
738
|
+
)
|
|
739
|
+
return wrap_prompt(
|
|
740
|
+
agent_identity="BEHAVIORAL EQUIVALENCE GUARDIAN",
|
|
741
|
+
mission=(
|
|
742
|
+
"Your goal is to ensure migrated code behaves identically to legacy code. "
|
|
743
|
+
"You enumerate legacy public APIs, capture behavioral contracts as a golden master, "
|
|
744
|
+
"design equivalence tests comparing old vs new, classify divergence, and issue "
|
|
745
|
+
"a PASS or FAIL gate decision. PASS unblocks cutover_engineer. FAIL returns to developer."
|
|
746
|
+
),
|
|
747
|
+
rules_content=rules,
|
|
748
|
+
agent_id="parity_tester",
|
|
749
|
+
)
|
|
750
|
+
|
|
751
|
+
|
|
752
|
+
def get_cutover_engineer_prompt() -> str:
|
|
753
|
+
"""Generate prompt for Cutover Engineer agent (feature flag ramp + rollback governance)."""
|
|
754
|
+
rules = load_rules(
|
|
755
|
+
[
|
|
756
|
+
"operations/cutover_protocol.md",
|
|
757
|
+
"common/core_protocol.md",
|
|
758
|
+
"operations/completion.md",
|
|
759
|
+
]
|
|
760
|
+
)
|
|
761
|
+
return wrap_prompt(
|
|
762
|
+
agent_identity="CUTOVER EXECUTION GUARDIAN",
|
|
763
|
+
mission=(
|
|
764
|
+
"Your goal is to execute migration batch cutover safely. "
|
|
765
|
+
"You verify parity gate passed, produce a step-by-step cutover runbook "
|
|
766
|
+
"with feature flag ramp schedule and rollback triggers, and govern the "
|
|
767
|
+
"post-cutover validation window before decommissioning legacy code. "
|
|
768
|
+
"PASS gate unblocks scrum_master. BLOCKED gate returns to parity_tester."
|
|
769
|
+
),
|
|
770
|
+
rules_content=rules,
|
|
771
|
+
agent_id="cutover_engineer",
|
|
772
|
+
)
|