@@ -158,47 +158,92 @@ def _parse_int(s: str) -> int:
158158 return 0
159159
160160
161- _GENERATION_SYSTEM_PROMPT = """\
161+ _GENERATION_SYSTEM_PROMPT_HEADER = """\
162162 You are a network topology engineer generating ngraph scenario YAML files.
163163
164164You will receive a connectivity idea and must produce a complete ngraph
165165scenario YAML. After each attempt, you will receive the ngraph inspect
166166output showing what was actually built. Compare it against the original
167167intent and fix any mismatches.
168168
169- CRITICAL: The top-level keys must be: seed, network, risk_groups, demands,
170- failures, workflow. Nodes and links go INSIDE the network key.
171-
172- Minimal working example:
173-
174- seed: 42
175- network:
176- nodes:
177- A: {}
178- B: {}
179- links:
180- - source: A
181- target: B
182- capacity: 100
183- cost: 1
184- demands:
185- tm:
186- - source: ^A$
187- target: ^B$
188- volume: 10
189- mode: combine
190- flow_policy: SHORTEST_PATHS_ECMP
191- workflow:
192- - type: MaximumSupportedDemand
193- name: msd_baseline
194- demand_set: tm
195- resolution: 0.1
169+ Return ONLY valid YAML. No markdown fences, no explanation.
170+ """
196171
197- All links are bidirectional by default (ngraph adds reverse automatically).
198- Use `risk_groups: [name]` on link definitions to assign to failure domains.
199- Failure policies use `scope: node|link|risk_group` with `mode: choice` and
200- `match.conditions` to select targets.
172+ # Loaded at module import from the skills directory if available,
173+ # otherwise falls back to a built-in minimal reference.
174+ _DSL_REFERENCE : str | None = None
175+
176+
177+ def _load_dsl_reference () -> str :
178+ """Load the ngraph DSL skill reference for use as system prompt context."""
179+ global _DSL_REFERENCE
180+ if _DSL_REFERENCE is not None :
181+ return _DSL_REFERENCE
182+
183+ # Try loading from the skills directory
184+ from pathlib import Path
185+
186+ skill_paths = [
187+ Path (__file__ ).parent .parent .parent .parent
188+ / "skills"
189+ / "netgraph-dsl"
190+ / "SKILL.md" ,
191+ Path .home ()
192+ / "ws"
193+ / "project_netgraph"
194+ / "skills"
195+ / "netgraph-dsl"
196+ / "SKILL.md" ,
197+ ]
198+ for skill_path in skill_paths :
199+ if skill_path .exists ():
200+ _DSL_REFERENCE = skill_path .read_text ()
201+ return _DSL_REFERENCE
202+
203+ # Fallback: built-in minimal reference
204+ _DSL_REFERENCE = """\
205+ CRITICAL RULES:
206+ - Top-level keys: seed, network, risk_groups, demands, failures, workflow
207+ - nodes and links go INSIDE the network key
208+ - All links are bidirectional (ngraph adds reverse automatically)
209+ - Use risk_groups: [name] on link defs to assign failure domains
210+ - Node attrs enable failure targeting: {role: bb} matches scope: node
211+
212+ Failure policy structure (EXACT nesting required):
213+ failures:
214+ policy_name:
215+ modes:
216+ - weight: 1.0
217+ rules:
218+ - scope: node # node | link | risk_group
219+ mode: choice # choice | all | random
220+ count: 1
221+ match:
222+ conditions:
223+ - attr: role
224+ op: "==" # == | != | contains | in
225+ value: bb
226+
227+ TrafficMatrixPlacement workflow step (all fields required):
228+ - type: TrafficMatrixPlacement
229+ name: tm_step
230+ demand_set: tm
231+ failure_policy: policy_name
232+ iterations: 10
233+ parallelism: 1
234+ placement_rounds: auto
235+ seed: 42
236+ include_flow_details: true
237+ alpha_from_step: msd_baseline
238+ alpha_from_field: data.alpha_star
201239"""
240+ return _DSL_REFERENCE
241+
242+
243+ def _get_generation_system_prompt () -> str :
244+ """Build the full system prompt for scenario generation."""
245+ return _GENERATION_SYSTEM_PROMPT_HEADER + "\n " + _load_dsl_reference ()
246+
202247
203248_GENERATION_PROMPT_TEMPLATE = """\
204249 Generate a complete ngraph scenario YAML for this connectivity idea:
@@ -281,7 +326,7 @@ def run_generation_loop(
281326 validation_errors = validation_errors ,
282327 )
283328
284- response = backend .generate (prompt , system = _GENERATION_SYSTEM_PROMPT )
329+ response = backend .generate (prompt , system = _get_generation_system_prompt () )
285330
286331 # Extract YAML from response
287332 yaml_text = _extract_yaml (response )
0 commit comments