RthItalia commited on
Commit
cad26d4
·
verified ·
1 Parent(s): a6a3b31

Deploy ContextForge with Codex

Browse files
Files changed (7) hide show
  1. .env.example +5 -0
  2. .gitignore +6 -0
  3. README.md +78 -6
  4. app.py +1007 -0
  5. assets/style.css +231 -0
  6. requirements.txt +4 -0
  7. test_contextforge.py +79 -0
.env.example ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ CONTEXTFORGE_ENABLE_MODEL=1
2
+ CONTEXTFORGE_MODEL_ID=Qwen/Qwen2.5-0.5B-Instruct
3
+ CONTEXTFORGE_MID_MODEL_ID=RthItalia/nano_compact_3b_qkvfp16
4
+ CONTEXTFORGE_HIGH_MODEL_ID=Qwen/Qwen3-32B
5
+ CONTEXTFORGE_MAX_NEW_TOKENS=1800
.gitignore ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ __pycache__/
2
+ *.py[cod]
3
+ .env
4
+ .venv/
5
+ gradio.out.log
6
+ gradio.err.log
README.md CHANGED
@@ -1,13 +1,85 @@
1
  ---
2
  title: ContextForge
3
- emoji: 🐢
4
- colorFrom: pink
5
- colorTo: gray
6
  sdk: gradio
7
- sdk_version: 6.16.0
8
- python_version: '3.13'
9
  app_file: app.py
10
  pinned: false
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  title: ContextForge
3
+ emoji: ⚒️
4
+ colorFrom: blue
5
+ colorTo: green
6
  sdk: gradio
7
+ sdk_version: 5.50.0
 
8
  app_file: app.py
9
  pinned: false
10
  ---
11
 
12
+ # ContextForge / Agent Prompt Compiler
13
+
14
+ ContextForge compiles messy software, app, and agent ideas into executable prompt architectures. It is a compiler pipeline, not a generic prompt generator.
15
+
16
+ **GitHub:** https://github.com/rthgit/ContextForge
17
+
18
+ **Competition Gradio Space:** https://huggingface.co/spaces/build-small-hackathon/ContextForge
19
+
20
+ **Backup Gradio Space:** https://huggingface.co/spaces/RthItalia/ContextForge
21
+
22
+ The backend always executes seven isolated modules sequentially:
23
+
24
+ 1. intake analysis
25
+ 2. topology decision
26
+ 3. Vital Few / Vital Spot extraction
27
+ 4. reasoning architecture selection
28
+ 5. prompt pack generation
29
+ 6. QA / repair
30
+ 7. final assembly
31
+
32
+ Every module attempts its own small-model call. If one call fails, only that stage uses a deterministic fallback and the pipeline continues. Runtime Details shows the source used by every stage.
33
+
34
+ ## Topologies
35
+
36
+ - Single Prompt
37
+ - Cascade
38
+ - Context Pack
39
+ - Agent Workflow
40
+
41
+ Auto topology uses Cascade when multiple expertise areas or dependent outputs are required. Agent Workflow is preferred for agentic or critical-risk work. Context Pack stabilizes incomplete briefs.
42
+
43
+ ## Safety
44
+
45
+ - Private reasoning remains internal.
46
+ - Generated prompts never request full chain of thought.
47
+ - Controlled Tree of Thought exposes only `strategy | upside | risk | cost | selected`.
48
+ - Public reasoning fields are limited to decision summary, assumptions, risks, verification steps, and final answer.
49
+ - QA repairs missing tags, contracts, verification, repair logic, and unsafe reasoning requests.
50
+
51
+ ## Runtime
52
+
53
+ Recommended Hugging Face Space variables:
54
+
55
+ ```text
56
+ CONTEXTFORGE_ENABLE_MODEL=1
57
+ CONTEXTFORGE_MODEL_ID=Qwen/Qwen2.5-0.5B-Instruct
58
+ CONTEXTFORGE_MID_MODEL_ID=RthItalia/nano_compact_3b_qkvfp16
59
+ CONTEXTFORGE_HIGH_MODEL_ID=Qwen/Qwen3-32B
60
+ CONTEXTFORGE_MAX_NEW_TOKENS=1800
61
+ ```
62
+
63
+ Runtime selection:
64
+
65
+ 1. high model only when CUDA is available
66
+ 2. compact mid model when CUDA is available
67
+ 3. Qwen 0.5B on public CPU Space
68
+ 4. deterministic stage-level fallback
69
+
70
+ For a fast local deterministic run:
71
+
72
+ ```powershell
73
+ $env:CONTEXTFORGE_ENABLE_MODEL='0'
74
+ python app.py
75
+ ```
76
+
77
+ ## Local QA
78
+
79
+ ```powershell
80
+ python -m py_compile app.py
81
+ python test_contextforge.py
82
+ python app.py
83
+ ```
84
+
85
+ The QA script verifies all four topologies, independent stage execution, required tags, chain-of-thought safety, controlled Tree of Thought output, and stage-level fallback continuity.
app.py ADDED
@@ -0,0 +1,1007 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import os
5
+ import re
6
+ import time
7
+ from dataclasses import dataclass
8
+ from functools import lru_cache
9
+ from typing import Any, Callable
10
+
11
+
12
+ APP_TITLE = "ContextForge"
13
+ APP_SUBTITLE = "Agent Prompt Compiler"
14
+ DEFAULT_MODEL_ID = "Qwen/Qwen2.5-0.5B-Instruct"
15
+ DEFAULT_MID_MODEL_ID = "RthItalia/nano_compact_3b_qkvfp16"
16
+ DEFAULT_HIGH_MODEL_ID = "Qwen/Qwen3-32B"
17
+ REQUIRED_PROMPT_TAGS = [
18
+ "ROLE",
19
+ "COGNITIVE_LAYERS",
20
+ "KAHNEMAN_SYSTEM2",
21
+ "PARETO_80_20",
22
+ "VITAL_SPOT",
23
+ "REASONING_PROTOCOL",
24
+ "AGENTIC_LOOP",
25
+ "ACTION",
26
+ "FORMAT_AND_TARGET",
27
+ "QA_CHECKS",
28
+ ]
29
+ TOPOLOGIES = ["Auto", "Single Prompt", "Cascade", "Context Pack", "Agent Workflow"]
30
+ REASONING_LAYERS = [
31
+ "CRAFT",
32
+ "Kahneman System 2",
33
+ "Pareto 80/20",
34
+ "Agentic Loop",
35
+ "Tree of Thought controlled",
36
+ "Private CoT",
37
+ "Self-Correction",
38
+ "Sentinel Recovery",
39
+ ]
40
+ STAGE_NAMES = [
41
+ "intake_analysis",
42
+ "topology_decision",
43
+ "vital_structure",
44
+ "reasoning_architecture",
45
+ "prompt_pack_generation",
46
+ "qa_repair",
47
+ "final_assembly",
48
+ ]
49
+
50
+
51
+ def parse_bool_env(name: str, default: bool = False) -> bool:
52
+ raw = os.getenv(name)
53
+ if raw is None:
54
+ return default
55
+ return raw.strip().lower() in {"1", "true", "yes", "on"}
56
+
57
+
58
+ def parse_int_env(name: str, default: int, minimum: int, maximum: int) -> int:
59
+ try:
60
+ value = int(os.getenv(name, str(default)))
61
+ except ValueError:
62
+ value = default
63
+ return max(minimum, min(maximum, value))
64
+
65
+
66
+ MODEL_ENABLED = parse_bool_env("CONTEXTFORGE_ENABLE_MODEL", False)
67
+ MODEL_ID = os.getenv("CONTEXTFORGE_MODEL_ID", DEFAULT_MODEL_ID)
68
+ MID_MODEL_ID = os.getenv("CONTEXTFORGE_MID_MODEL_ID", DEFAULT_MID_MODEL_ID)
69
+ HIGH_MODEL_ID = os.getenv("CONTEXTFORGE_HIGH_MODEL_ID", DEFAULT_HIGH_MODEL_ID)
70
+ MAX_NEW_TOKENS = parse_int_env("CONTEXTFORGE_MAX_NEW_TOKENS", 1800, 256, 4096)
71
+ MAX_INPUT_CHARS = parse_int_env("CONTEXTFORGE_MAX_INPUT_CHARS", 12000, 2000, 40000)
72
+
73
+
74
+ @dataclass
75
+ class StageResult:
76
+ data: dict[str, Any]
77
+ source: str
78
+ model_id: str
79
+ elapsed_ms: int
80
+ note: str = ""
81
+
82
+ def runtime_row(self, stage: str) -> dict[str, Any]:
83
+ return {
84
+ "stage": stage,
85
+ "source": self.source,
86
+ "model_id": self.model_id,
87
+ "elapsed_ms": self.elapsed_ms,
88
+ "note": self.note,
89
+ }
90
+
91
+
92
+ _RUNTIME_TRACE: list[dict[str, Any]] = []
93
+
94
+
95
+ def clean_text(value: Any, limit: int = 4000) -> str:
96
+ text = "" if value is None else str(value)
97
+ text = text.replace("\x00", " ")
98
+ text = re.sub(r"[ \t]+", " ", text)
99
+ text = re.sub(r"\n{3,}", "\n\n", text).strip()
100
+ return text[:limit]
101
+
102
+
103
+ def clean_list(value: Any, limit: int = 8) -> list[str]:
104
+ if isinstance(value, str):
105
+ candidates = re.split(r"[,;\n]+", value)
106
+ elif isinstance(value, list):
107
+ candidates = value
108
+ else:
109
+ candidates = []
110
+ result = []
111
+ for item in candidates:
112
+ cleaned = clean_text(item, 240)
113
+ if cleaned and cleaned not in result:
114
+ result.append(cleaned)
115
+ return result[:limit]
116
+
117
+
118
+ def json_text(value: Any) -> str:
119
+ return json.dumps(value, ensure_ascii=False, indent=2, sort_keys=True)
120
+
121
+
122
+ def parse_json_object(raw: str) -> dict[str, Any] | None:
123
+ decoder = json.JSONDecoder()
124
+ for match in re.finditer(r"\{", raw or ""):
125
+ try:
126
+ parsed, _ = decoder.raw_decode(raw[match.start() :])
127
+ except json.JSONDecodeError:
128
+ continue
129
+ if isinstance(parsed, dict):
130
+ return parsed
131
+ return None
132
+
133
+
134
+ def merge_known(fallback: dict[str, Any], candidate: dict[str, Any] | None) -> dict[str, Any]:
135
+ if not candidate:
136
+ return fallback
137
+ merged = dict(fallback)
138
+ for key, fallback_value in fallback.items():
139
+ candidate_value = candidate.get(key)
140
+ if candidate_value is None:
141
+ continue
142
+ if isinstance(fallback_value, list):
143
+ items = clean_list(candidate_value, max(3, len(fallback_value) + 3))
144
+ if items:
145
+ merged[key] = items
146
+ elif isinstance(fallback_value, dict) and isinstance(candidate_value, dict):
147
+ merged[key] = {**fallback_value, **candidate_value}
148
+ elif isinstance(fallback_value, int):
149
+ try:
150
+ merged[key] = int(candidate_value)
151
+ except (TypeError, ValueError):
152
+ pass
153
+ else:
154
+ cleaned = clean_text(candidate_value, 16000)
155
+ if cleaned:
156
+ merged[key] = cleaned
157
+ return merged
158
+
159
+
160
+ def model_candidates() -> list[tuple[str, str, bool]]:
161
+ candidates = [
162
+ ("high", HIGH_MODEL_ID, True),
163
+ ("mid", MID_MODEL_ID, True),
164
+ ("public_cpu", MODEL_ID, False),
165
+ ]
166
+ seen: set[str] = set()
167
+ return [
168
+ item
169
+ for item in candidates
170
+ if item[1].strip() and not (item[1] in seen or seen.add(item[1]))
171
+ ]
172
+
173
+
174
+ @lru_cache(maxsize=1)
175
+ def load_model() -> tuple[Any | None, Any | None, str, str]:
176
+ if not MODEL_ENABLED:
177
+ return None, None, "disabled", "model disabled by CONTEXTFORGE_ENABLE_MODEL"
178
+ try:
179
+ import torch
180
+ from transformers import AutoModelForCausalLM, AutoTokenizer
181
+ except Exception as exc:
182
+ return None, None, "unavailable", f"dependencies unavailable: {type(exc).__name__}: {exc}"
183
+
184
+ failures: list[str] = []
185
+ for role, candidate_id, requires_cuda in model_candidates():
186
+ if requires_cuda and not torch.cuda.is_available():
187
+ failures.append(f"{role}: CUDA unavailable")
188
+ continue
189
+ try:
190
+ tokenizer = AutoTokenizer.from_pretrained(candidate_id, trust_remote_code=True, use_fast=True)
191
+ if tokenizer.pad_token_id is None and tokenizer.eos_token_id is not None:
192
+ tokenizer.pad_token = tokenizer.eos_token
193
+ kwargs: dict[str, Any] = {"trust_remote_code": True, "low_cpu_mem_usage": True}
194
+ if torch.cuda.is_available():
195
+ kwargs["device_map"] = "cuda"
196
+ kwargs["torch_dtype"] = torch.float16
197
+ model = AutoModelForCausalLM.from_pretrained(candidate_id, **kwargs)
198
+ model.eval()
199
+ return tokenizer, model, candidate_id, f"selected {role}; " + "; ".join(failures)
200
+ except Exception as exc:
201
+ failures.append(f"{role}: {type(exc).__name__}: {exc}")
202
+ return None, None, "unavailable", " | ".join(failures) or "no model candidates"
203
+
204
+
205
+ def format_chat_prompt(tokenizer: Any, stage: str, instruction: str, payload: dict[str, Any]) -> str:
206
+ system = (
207
+ "You are one isolated module inside ContextForge, an agent prompt compiler. "
208
+ "Return only a valid JSON object. Private reasoning internal only. "
209
+ "Never reveal chain of thought, hidden branches, or internal deliberation. "
210
+ "Public fields may contain only decision summaries, assumptions, risks, verification steps, and outputs."
211
+ )
212
+ user = f"MODULE: {stage}\nTASK:\n{instruction}\nINPUT:\n{json_text(payload)}"
213
+ try:
214
+ if getattr(tokenizer, "chat_template", None):
215
+ return tokenizer.apply_chat_template(
216
+ [{"role": "system", "content": system}, {"role": "user", "content": user}],
217
+ tokenize=False,
218
+ add_generation_prompt=True,
219
+ )
220
+ except Exception:
221
+ pass
222
+ return f"{system}\n\n{user}\n\nJSON:"
223
+
224
+
225
+ def generate_json(stage: str, instruction: str, payload: dict[str, Any]) -> tuple[dict[str, Any] | None, str, str]:
226
+ tokenizer, model, selected_id, load_note = load_model()
227
+ if tokenizer is None or model is None:
228
+ return None, selected_id, load_note
229
+ try:
230
+ import torch
231
+
232
+ prompt = format_chat_prompt(tokenizer, stage, instruction, payload)
233
+ inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=6144)
234
+ device = getattr(model, "device", None)
235
+ if device is not None and str(device) != "meta":
236
+ inputs = {key: value.to(device) for key, value in inputs.items()}
237
+ with torch.no_grad():
238
+ output_ids = model.generate(
239
+ **inputs,
240
+ max_new_tokens=MAX_NEW_TOKENS,
241
+ do_sample=False,
242
+ repetition_penalty=1.05,
243
+ pad_token_id=tokenizer.eos_token_id,
244
+ )
245
+ raw = tokenizer.decode(output_ids[0][inputs["input_ids"].shape[-1] :], skip_special_tokens=True)
246
+ parsed = parse_json_object(raw)
247
+ if parsed is None:
248
+ return None, selected_id, f"{load_note}; invalid JSON output"
249
+ return parsed, selected_id, load_note
250
+ except Exception as exc:
251
+ return None, selected_id, f"{load_note}; generation failed: {type(exc).__name__}: {exc}"
252
+
253
+
254
+ def run_stage(
255
+ stage: str,
256
+ instruction: str,
257
+ payload: dict[str, Any],
258
+ fallback_factory: Callable[[], dict[str, Any]],
259
+ validator: Callable[[dict[str, Any]], dict[str, Any]] | None = None,
260
+ ) -> dict[str, Any]:
261
+ started = time.perf_counter()
262
+ fallback = fallback_factory()
263
+ candidate, selected_id, note = generate_json(stage, instruction, payload)
264
+ source = "small_model"
265
+ if candidate is None:
266
+ data = fallback
267
+ source = "deterministic_fallback"
268
+ else:
269
+ data = merge_known(fallback, candidate)
270
+ if validator:
271
+ try:
272
+ data = validator(data)
273
+ except Exception as exc:
274
+ data = fallback
275
+ source = "deterministic_fallback"
276
+ note = f"{note}; validation failed: {type(exc).__name__}: {exc}"
277
+ elapsed_ms = round((time.perf_counter() - started) * 1000)
278
+ result = StageResult(data=data, source=source, model_id=selected_id, elapsed_ms=elapsed_ms, note=note)
279
+ _RUNTIME_TRACE.append(result.runtime_row(stage))
280
+ return result.data
281
+
282
+
283
+ def infer_domain(payload: dict[str, Any]) -> str:
284
+ haystack = " ".join(clean_text(v, 1000).lower() for v in payload.values() if isinstance(v, str))
285
+ domains = [
286
+ ("software engineering", ["api", "code", "software", "app", "backend", "frontend"]),
287
+ ("agent systems", ["agent", "workflow", "tool", "autonomous", "mcp"]),
288
+ ("data and analytics", ["data", "dataset", "analytics", "dashboard", "sql"]),
289
+ ("creative production", ["story", "creative", "brand", "content", "design"]),
290
+ ]
291
+ for domain, signals in domains:
292
+ if any(signal in haystack for signal in signals):
293
+ return domain
294
+ return "general knowledge work"
295
+
296
+
297
+ def analyze_intake(input_payload: dict[str, Any]) -> dict[str, Any]:
298
+ payload = {key: clean_text(value, MAX_INPUT_CHARS) if isinstance(value, str) else value for key, value in input_payload.items()}
299
+
300
+ def fallback() -> dict[str, Any]:
301
+ missing = [
302
+ label
303
+ for key, label in [
304
+ ("project_idea", "project idea"),
305
+ ("target_user", "target user"),
306
+ ("build_target", "build target"),
307
+ ("output_contract", "output contract"),
308
+ ("verification_criteria", "verification criteria"),
309
+ ]
310
+ if not clean_text(payload.get(key), 200)
311
+ ]
312
+ complexity_signals = sum(
313
+ bool(clean_text(payload.get(key), 300))
314
+ for key in ["user_context", "project_context", "technical_context", "constraints", "inputs_files", "failure_modes"]
315
+ )
316
+ return {
317
+ "domain": infer_domain(payload),
318
+ "task_type": "design and implementation planning",
319
+ "risk_level": clean_text(payload.get("risk_level"), 40) or "Medium",
320
+ "input_type": "structured brief with free-text context",
321
+ "output_type": clean_text(payload.get("build_target"), 200) or "executable prompt architecture",
322
+ "missing_information": missing,
323
+ "complexity": "high" if complexity_signals >= 5 else "medium" if complexity_signals >= 2 else "low",
324
+ "decision_summary": "Normalize the brief into an explicit compiler input before selecting topology.",
325
+ "assumptions": ["Unspecified details may be resolved conservatively during execution."],
326
+ "risks": clean_list(payload.get("failure_modes"), 5) or ["Ambiguous output contract", "Insufficient verification criteria"],
327
+ }
328
+
329
+ instruction = (
330
+ "Classify domain, task type, risk level, input type, output type, missing information, complexity, "
331
+ "decision summary, assumptions, and risks. Do not solve the task."
332
+ )
333
+ return run_stage("intake_analysis", instruction, payload, fallback)
334
+
335
+
336
+ def decide_topology(analysis: dict[str, Any], user_topology_choice: str) -> dict[str, Any]:
337
+ choice = user_topology_choice if user_topology_choice in TOPOLOGIES else "Auto"
338
+
339
+ def fallback() -> dict[str, Any]:
340
+ risk = clean_text(analysis.get("risk_level"), 40).lower()
341
+ complexity = clean_text(analysis.get("complexity"), 40).lower()
342
+ domain = clean_text(analysis.get("domain"), 100).lower()
343
+ if choice != "Auto":
344
+ topology = choice
345
+ reason = "Explicit user topology choice."
346
+ elif "agent" in domain or risk == "critical":
347
+ topology = "Agent Workflow"
348
+ reason = "Agentic or critical-risk work benefits from explicit execution and recovery states."
349
+ elif complexity == "high":
350
+ topology = "Cascade"
351
+ reason = "Multiple context areas and dependent outputs require sequential specialist prompts."
352
+ elif analysis.get("missing_information"):
353
+ topology = "Context Pack"
354
+ reason = "A reusable context contract should stabilize unresolved inputs."
355
+ else:
356
+ topology = "Single Prompt"
357
+ reason = "The task is bounded enough for one complete execution contract."
358
+ roles_by_topology = {
359
+ "Single Prompt": ["Lead Executor"],
360
+ "Cascade": ["Brief Analyst", "Solution Architect", "Builder", "Verifier"],
361
+ "Context Pack": ["Context Curator", "Execution Prompt Author"],
362
+ "Agent Workflow": ["Planner", "Executor", "Verifier", "Recovery Sentinel"],
363
+ }
364
+ roles = roles_by_topology[topology]
365
+ return {
366
+ "topology": topology,
367
+ "reason": reason,
368
+ "number_of_prompts": len(roles),
369
+ "roles": roles,
370
+ "handoff_contract": "Each stage receives structured upstream output and returns a verifiable downstream artifact.",
371
+ }
372
+
373
+ instruction = (
374
+ "Choose Single Prompt, Cascade, Context Pack, or Agent Workflow. Use Cascade when multiple expertise areas "
375
+ "are required, task A feeds task B, or more than six unrelated ACTION sections are required. Respect an "
376
+ "explicit non-Auto user choice. Return topology, reason, number_of_prompts, roles, and handoff_contract."
377
+ )
378
+ return run_stage("topology_decision", instruction, {"analysis": analysis, "user_choice": choice}, fallback)
379
+
380
+
381
+ def extract_vital_structure(analysis: dict[str, Any], topology: dict[str, Any]) -> dict[str, Any]:
382
+ def fallback() -> dict[str, Any]:
383
+ vital_few = [
384
+ "A precise output contract",
385
+ "A topology matched to dependency structure",
386
+ "Verifiable acceptance criteria",
387
+ "Explicit failure and recovery behavior",
388
+ ]
389
+ if analysis.get("missing_information"):
390
+ vital_few.insert(0, "Resolution of critical missing context")
391
+ return {
392
+ "vital_few": vital_few[:5],
393
+ "vital_spot": "The output contract: if it is ambiguous, every downstream prompt can appear complete while producing the wrong artifact.",
394
+ "vital_spot_guard": "Restate the output contract before execution and fail QA when required fields or verification evidence are absent.",
395
+ "decision_summary": f"Optimize the {topology.get('topology', 'selected')} architecture around a small set of quality drivers.",
396
+ }
397
+
398
+ instruction = (
399
+ "Extract three to five Vital Few elements that determine most output quality and one Vital Spot whose failure "
400
+ "breaks the workflow. Include a concrete guard for the Vital Spot."
401
+ )
402
+ return run_stage("vital_structure", instruction, {"analysis": analysis, "topology": topology}, fallback)
403
+
404
+
405
+ def select_reasoning_architecture(
406
+ analysis: dict[str, Any],
407
+ topology: dict[str, Any],
408
+ selected_layers: list[str],
409
+ ) -> dict[str, Any]:
410
+ selected = [layer for layer in selected_layers if layer in REASONING_LAYERS]
411
+
412
+ def fallback() -> dict[str, Any]:
413
+ layers = selected or ["CRAFT", "Pareto 80/20", "Private CoT", "Self-Correction", "Sentinel Recovery"]
414
+ if topology.get("topology") in {"Cascade", "Agent Workflow"} and "Agentic Loop" not in layers:
415
+ layers.append("Agentic Loop")
416
+ if clean_text(analysis.get("risk_level"), 30).lower() in {"high", "critical"} and "Kahneman System 2" not in layers:
417
+ layers.append("Kahneman System 2")
418
+ configurations = {
419
+ layer: {
420
+ "purpose": {
421
+ "CRAFT": "Bind context, role, action, format, and target.",
422
+ "Kahneman System 2": "Slow down at consequential decisions and verify assumptions.",
423
+ "Pareto 80/20": "Prioritize the few actions that drive most value.",
424
+ "Agentic Loop": "Plan, act, observe, verify, and recover.",
425
+ "Tree of Thought controlled": "Compare strategies without exposing hidden branches.",
426
+ "Private CoT": "Keep reasoning internal and publish only summaries and evidence.",
427
+ "Self-Correction": "Repair failed checks before final output.",
428
+ "Sentinel Recovery": "Detect blocked or degraded states and continue safely.",
429
+ }[layer],
430
+ "public_output": "decision summary, assumptions, risks, verification steps, final answer",
431
+ }
432
+ for layer in layers
433
+ }
434
+ return {
435
+ "selected_layers": layers,
436
+ "configurations": configurations,
437
+ "private_reasoning_policy": "Private reasoning internal only.",
438
+ "tree_of_thought_policy": "Expose only: strategy | upside | risk | cost | selected.",
439
+ }
440
+
441
+ instruction = (
442
+ "Select and configure only useful reasoning layers. Private CoT must remain internal. Controlled Tree of "
443
+ "Thought may expose only strategy, upside, risk, cost, selected. Return selected_layers, configurations, "
444
+ "private_reasoning_policy, and tree_of_thought_policy."
445
+ )
446
+ return run_stage(
447
+ "reasoning_architecture",
448
+ instruction,
449
+ {"analysis": analysis, "topology": topology, "selected_layers": selected},
450
+ fallback,
451
+ )
452
+
453
+
454
+ def prompt_block(
455
+ title: str,
456
+ role: str,
457
+ action: str,
458
+ analysis: dict[str, Any],
459
+ topology: dict[str, Any],
460
+ vital: dict[str, Any],
461
+ reasoning_architecture: dict[str, Any],
462
+ output_contract: str,
463
+ verification_criteria: str,
464
+ ) -> str:
465
+ layers = ", ".join(reasoning_architecture.get("selected_layers", []))
466
+ vital_few = "\n".join(f"- {item}" for item in vital.get("vital_few", []))
467
+ return f"""# {title}
468
+
469
+ [ROLE]
470
+ You are {role}. Own the assigned artifact and its verification. Do not impersonate other stages.
471
+
472
+ [COGNITIVE_LAYERS]
473
+ Use: {layers}. Private reasoning internal only. Public output may include only decision summary, assumptions, risks, verification steps, and final answer.
474
+
475
+ [KAHNEMAN_SYSTEM2]
476
+ Pause before consequential decisions. Check assumptions, dependency order, risk, and evidence before committing.
477
+
478
+ [PARETO_80_20]
479
+ Prioritize these Vital Few:
480
+ {vital_few}
481
+
482
+ [VITAL_SPOT]
483
+ {vital.get("vital_spot", "The output contract is the single failure point.")}
484
+ Guard: {vital.get("vital_spot_guard", "Fail QA when the contract is incomplete.")}
485
+
486
+ [REASONING_PROTOCOL]
487
+ 1. Normalize the available context.
488
+ 2. Identify assumptions and risks.
489
+ 3. Compare options only when useful. If using controlled Tree of Thought, expose only: strategy | upside | risk | cost | selected.
490
+ 4. Execute the selected strategy.
491
+ 5. Verify against the output contract.
492
+ Never reveal chain of thought or hidden branches.
493
+
494
+ [AGENTIC_LOOP]
495
+ PLAN -> ACT -> OBSERVE -> VERIFY -> REPAIR or COMPLETE.
496
+ On blocked execution, invoke Sentinel Recovery: state the blocker, preserve valid work, choose the safest viable fallback, and continue.
497
+
498
+ [ACTION]
499
+ {action}
500
+
501
+ [FORMAT_AND_TARGET]
502
+ Target topology: {topology.get("topology", "Single Prompt")}
503
+ Required output contract: {output_contract or "Return a complete, directly usable artifact with explicit assumptions and verification evidence."}
504
+
505
+ [QA_CHECKS]
506
+ - Required sections and fields are present.
507
+ - Claims and assumptions are distinguishable.
508
+ - Verification criteria are satisfied: {verification_criteria or "The output is complete, internally consistent, and directly executable."}
509
+ - No full chain of thought or hidden Tree of Thought branches are exposed.
510
+ - If a check fails, repair the artifact and rerun QA before returning it."""
511
+
512
+
513
+ def deterministic_prompt_pack(
514
+ analysis: dict[str, Any],
515
+ topology: dict[str, Any],
516
+ vital: dict[str, Any],
517
+ reasoning_architecture: dict[str, Any],
518
+ context: dict[str, Any],
519
+ ) -> dict[str, Any]:
520
+ topology_name = topology.get("topology", "Single Prompt")
521
+ roles = topology.get("roles", ["Lead Executor"])
522
+ project_idea = clean_text(context.get("project_idea"), 1800) or "Execute the supplied project brief."
523
+ output_contract = clean_text(context.get("output_contract"), 1600)
524
+ verification = clean_text(context.get("verification_criteria"), 1200)
525
+ prompts = []
526
+ for index, role in enumerate(roles, start=1):
527
+ if topology_name == "Single Prompt":
528
+ action = f"Turn this brief into the required artifact:\n{project_idea}"
529
+ elif topology_name == "Context Pack":
530
+ action = (
531
+ "Create a reusable, source-aware context pack that separates facts, assumptions, constraints, open "
532
+ "questions, and execution instructions."
533
+ if index == 1
534
+ else "Use the approved context pack to produce the final execution prompt and verification contract."
535
+ )
536
+ elif topology_name == "Agent Workflow":
537
+ agent_actions = {
538
+ "Planner": "Convert the brief into ordered tasks, dependencies, stop conditions, and acceptance tests.",
539
+ "Executor": "Execute the approved plan and return artifacts plus evidence.",
540
+ "Verifier": "Test artifacts against acceptance criteria and identify repair actions.",
541
+ "Recovery Sentinel": "Handle blockers, failed checks, and degraded model/tool states without losing valid work.",
542
+ }
543
+ action = agent_actions.get(role, f"Execute the {role} stage and return a structured handoff.")
544
+ else:
545
+ action = f"Execute stage {index} as {role}; consume the previous structured handoff and produce the next verifiable artifact."
546
+ prompts.append(
547
+ prompt_block(
548
+ f"Prompt {index}: {role}",
549
+ role,
550
+ action,
551
+ analysis,
552
+ topology,
553
+ vital,
554
+ reasoning_architecture,
555
+ output_contract,
556
+ verification,
557
+ )
558
+ )
559
+ execution_plan = [
560
+ f"Run {role}; validate its output contract; pass only verified artifacts downstream."
561
+ for role in roles
562
+ ]
563
+ return {
564
+ "topology": topology_name,
565
+ "prompts": prompts,
566
+ "execution_plan": execution_plan,
567
+ "output_contract": output_contract or "Complete artifact, assumptions, risks, verification steps, final answer.",
568
+ }
569
+
570
+
571
+ def validate_prompt_pack(data: dict[str, Any]) -> dict[str, Any]:
572
+ prompts = data.get("prompts")
573
+ if not isinstance(prompts, list) or not prompts:
574
+ raise ValueError("prompt pack is empty")
575
+ cleaned_prompts = [clean_text(prompt, 30000) for prompt in prompts if clean_text(prompt, 30000)]
576
+ if not cleaned_prompts:
577
+ raise ValueError("prompt pack contains no usable prompts")
578
+ for prompt in cleaned_prompts:
579
+ missing = [tag for tag in REQUIRED_PROMPT_TAGS if f"[{tag}]" not in prompt]
580
+ if missing:
581
+ raise ValueError(f"prompt missing required tags: {', '.join(missing)}")
582
+ data["prompts"] = cleaned_prompts
583
+ return data
584
+
585
+
586
+ def generate_prompt_pack(
587
+ analysis: dict[str, Any],
588
+ topology: dict[str, Any],
589
+ vital: dict[str, Any],
590
+ reasoning_architecture: dict[str, Any],
591
+ context: dict[str, Any] | None = None,
592
+ ) -> dict[str, Any]:
593
+ context = context or {}
594
+
595
+ def fallback() -> dict[str, Any]:
596
+ return deterministic_prompt_pack(analysis, topology, vital, reasoning_architecture, context)
597
+
598
+ instruction = (
599
+ "Generate the complete prompt pack for the selected topology. Every prompt must contain all required tags: "
600
+ + ", ".join(REQUIRED_PROMPT_TAGS)
601
+ + ". Never request or reveal full chain of thought. Use exactly 'Private reasoning internal only.' "
602
+ "Controlled Tree of Thought exposes only strategy | upside | risk | cost | selected. Return topology, prompts, "
603
+ "execution_plan, and output_contract."
604
+ )
605
+ return run_stage(
606
+ "prompt_pack_generation",
607
+ instruction,
608
+ {
609
+ "analysis": analysis,
610
+ "topology": topology,
611
+ "vital": vital,
612
+ "reasoning_architecture": reasoning_architecture,
613
+ "context": context,
614
+ },
615
+ fallback,
616
+ validate_prompt_pack,
617
+ )
618
+
619
+
620
+ def repair_prompt_text(prompt: str) -> tuple[str, list[str]]:
621
+ repaired = clean_text(prompt, 30000)
622
+ repairs: list[str] = []
623
+ forbidden = [
624
+ r"reveal (?:your|the) (?:full )?chain of thought",
625
+ r"show (?:your|the) (?:full )?chain of thought",
626
+ r"expose hidden branches",
627
+ ]
628
+ for pattern in forbidden:
629
+ if re.search(pattern, repaired, flags=re.IGNORECASE):
630
+ repaired = re.sub(pattern, "provide a concise decision summary", repaired, flags=re.IGNORECASE)
631
+ repairs.append("Removed chain-of-thought leakage request.")
632
+ for tag in REQUIRED_PROMPT_TAGS:
633
+ if f"[{tag}]" not in repaired:
634
+ repaired += f"\n\n[{tag}]\nComplete this section before execution."
635
+ repairs.append(f"Added missing [{tag}] tag.")
636
+ if "Private reasoning internal only." not in repaired:
637
+ repaired = repaired.replace("[REASONING_PROTOCOL]", "[REASONING_PROTOCOL]\nPrivate reasoning internal only.", 1)
638
+ repairs.append("Added private reasoning policy.")
639
+ if "strategy | upside | risk | cost | selected" not in repaired:
640
+ repaired += "\n\nControlled Tree of Thought public schema: strategy | upside | risk | cost | selected."
641
+ repairs.append("Added controlled Tree of Thought public schema.")
642
+ return repaired, repairs
643
+
644
+
645
+ def deterministic_qa(prompt_pack: dict[str, Any]) -> dict[str, Any]:
646
+ repaired_prompts = []
647
+ issues: list[str] = []
648
+ for index, prompt in enumerate(prompt_pack.get("prompts", []), start=1):
649
+ repaired, repairs = repair_prompt_text(str(prompt))
650
+ repaired_prompts.append(repaired)
651
+ issues.extend(f"Prompt {index}: {repair}" for repair in repairs)
652
+ repaired_pack = dict(prompt_pack)
653
+ repaired_pack["prompts"] = repaired_prompts
654
+ missing_tags = [
655
+ tag
656
+ for tag in REQUIRED_PROMPT_TAGS
657
+ if any(f"[{tag}]" not in prompt for prompt in repaired_prompts)
658
+ ]
659
+ leakage = any(
660
+ re.search(r"(reveal|show|expose).{0,24}chain of thought", line, flags=re.IGNORECASE)
661
+ and not re.search(r"\b(never|do not|don't|must not|without)\b", line, flags=re.IGNORECASE)
662
+ for prompt in repaired_prompts
663
+ for line in prompt.splitlines()
664
+ )
665
+ checks = {
666
+ "all_required_tags": not missing_tags,
667
+ "strong_roles": all("[ROLE]" in prompt and len(prompt.split("[ROLE]", 1)[-1].strip()) > 20 for prompt in repaired_prompts),
668
+ "output_contracts": all("[FORMAT_AND_TARGET]" in prompt for prompt in repaired_prompts),
669
+ "no_chain_of_thought_leakage": not leakage,
670
+ "qa_present": all("[QA_CHECKS]" in prompt for prompt in repaired_prompts),
671
+ "repair_logic_present": all("REPAIR" in prompt for prompt in repaired_prompts),
672
+ "tree_of_thought_controlled": all("strategy | upside | risk | cost | selected" in prompt for prompt in repaired_prompts),
673
+ }
674
+ return {
675
+ "pass": all(checks.values()),
676
+ "issues": issues,
677
+ "checks": checks,
678
+ "repaired_prompt_pack": repaired_pack,
679
+ }
680
+
681
+
682
+ def validate_qa(data: dict[str, Any]) -> dict[str, Any]:
683
+ deterministic = deterministic_qa(data.get("repaired_prompt_pack", {}))
684
+ if not deterministic["pass"]:
685
+ return deterministic
686
+ data["pass"] = True
687
+ data["checks"] = deterministic["checks"]
688
+ data["repaired_prompt_pack"] = deterministic["repaired_prompt_pack"]
689
+ return data
690
+
691
+
692
+ def qa_repair_pass(prompt_pack: dict[str, Any]) -> dict[str, Any]:
693
+ def fallback() -> dict[str, Any]:
694
+ return deterministic_qa(prompt_pack)
695
+
696
+ instruction = (
697
+ "Check missing required tags, weak roles, missing output contracts, chain-of-thought leakage, missing QA, "
698
+ "missing repair logic, and uncontrolled Tree of Thought. Repair every issue. Return pass, issues, checks, "
699
+ "and repaired_prompt_pack. Never add hidden reasoning."
700
+ )
701
+ return run_stage("qa_repair", instruction, {"prompt_pack": prompt_pack}, fallback, validate_qa)
702
+
703
+
704
+ def score_metrics(
705
+ analysis: dict[str, Any],
706
+ topology: dict[str, Any],
707
+ qa: dict[str, Any],
708
+ ) -> dict[str, int]:
709
+ checks = qa.get("checks", {})
710
+ check_score = round(100 * sum(bool(value) for value in checks.values()) / max(1, len(checks)))
711
+ missing_count = len(analysis.get("missing_information", []))
712
+ coverage = max(45, 100 - missing_count * 10)
713
+ topology_score = 94 if topology.get("topology") in {"Cascade", "Agent Workflow"} else 86
714
+ risk_score = 96 if checks.get("no_chain_of_thought_leakage") and checks.get("repair_logic_present") else 68
715
+ return {
716
+ "Prompt Integrity": check_score,
717
+ "Context Coverage": coverage,
718
+ "Agent Readiness": topology_score,
719
+ "Risk Control": risk_score,
720
+ }
721
+
722
+
723
+ def deterministic_final(
724
+ analysis: dict[str, Any],
725
+ topology: dict[str, Any],
726
+ vital: dict[str, Any],
727
+ reasoning_architecture: dict[str, Any],
728
+ qa: dict[str, Any],
729
+ ) -> dict[str, Any]:
730
+ repaired_pack = qa.get("repaired_prompt_pack", {})
731
+ prompts = repaired_pack.get("prompts", [])
732
+ compiled_prompt_pack = "\n\n---\n\n".join(prompts)
733
+ architecture_analysis = {
734
+ "intake": analysis,
735
+ "topology": topology,
736
+ "vital_structure": vital,
737
+ "reasoning_architecture": reasoning_architecture,
738
+ }
739
+ execution_plan = repaired_pack.get("execution_plan", [])
740
+ repair_protocol = [
741
+ "Detect the failed check and preserve valid upstream artifacts.",
742
+ "Identify the smallest repair that restores the output contract.",
743
+ "Apply the repair, rerun QA, and continue only after verification passes.",
744
+ "If a model stage fails, use that stage's deterministic fallback and record it in Runtime Details.",
745
+ ]
746
+ return {
747
+ "architecture_analysis": architecture_analysis,
748
+ "prompt_pack": compiled_prompt_pack,
749
+ "execution_plan": execution_plan,
750
+ "qa_checklist": qa.get("checks", {}),
751
+ "repair_protocol": repair_protocol,
752
+ "metrics": score_metrics(analysis, topology, qa),
753
+ }
754
+
755
+
756
+ def assemble_final_output(
757
+ analysis: dict[str, Any],
758
+ topology: dict[str, Any],
759
+ vital: dict[str, Any],
760
+ reasoning_architecture: dict[str, Any],
761
+ qa: dict[str, Any],
762
+ ) -> dict[str, Any]:
763
+ def fallback() -> dict[str, Any]:
764
+ return deterministic_final(analysis, topology, vital, reasoning_architecture, qa)
765
+
766
+ instruction = (
767
+ "Assemble the final user-facing compiler result without adding hidden reasoning. Return architecture_analysis, "
768
+ "prompt_pack, execution_plan, qa_checklist, repair_protocol, and metrics. The prompt_pack must preserve all "
769
+ "required prompt tags exactly."
770
+ )
771
+
772
+ def validate_final(data: dict[str, Any]) -> dict[str, Any]:
773
+ prompt_pack = clean_text(data.get("prompt_pack"), 120000)
774
+ if not prompt_pack:
775
+ raise ValueError("final prompt pack is empty")
776
+ missing = [tag for tag in REQUIRED_PROMPT_TAGS if f"[{tag}]" not in prompt_pack]
777
+ if missing:
778
+ raise ValueError(f"final assembly lost required tags: {', '.join(missing)}")
779
+ data["prompt_pack"] = prompt_pack
780
+ return data
781
+
782
+ return run_stage(
783
+ "final_assembly",
784
+ instruction,
785
+ {
786
+ "analysis": analysis,
787
+ "topology": topology,
788
+ "vital": vital,
789
+ "reasoning_architecture": reasoning_architecture,
790
+ "qa": qa,
791
+ },
792
+ fallback,
793
+ validate_final,
794
+ )
795
+
796
+
797
+ def compile_context(
798
+ project_idea: str,
799
+ target_user: str,
800
+ build_target: str,
801
+ topology_choice: str,
802
+ risk_level: str,
803
+ output_language: str,
804
+ selected_layers: list[str],
805
+ user_context: str,
806
+ project_context: str,
807
+ technical_context: str,
808
+ constraints: str,
809
+ inputs_files: str,
810
+ output_contract: str,
811
+ failure_modes: str,
812
+ verification_criteria: str,
813
+ ) -> tuple[str, str, str, str, str, str]:
814
+ _RUNTIME_TRACE.clear()
815
+ payload = {
816
+ "project_idea": clean_text(project_idea, MAX_INPUT_CHARS),
817
+ "target_user": clean_text(target_user, 2000),
818
+ "build_target": clean_text(build_target, 2000),
819
+ "risk_level": clean_text(risk_level, 100),
820
+ "output_language": clean_text(output_language, 100),
821
+ "user_context": clean_text(user_context, MAX_INPUT_CHARS),
822
+ "project_context": clean_text(project_context, MAX_INPUT_CHARS),
823
+ "technical_context": clean_text(technical_context, MAX_INPUT_CHARS),
824
+ "constraints": clean_text(constraints, MAX_INPUT_CHARS),
825
+ "inputs_files": clean_text(inputs_files, MAX_INPUT_CHARS),
826
+ "output_contract": clean_text(output_contract, MAX_INPUT_CHARS),
827
+ "failure_modes": clean_text(failure_modes, MAX_INPUT_CHARS),
828
+ "verification_criteria": clean_text(verification_criteria, MAX_INPUT_CHARS),
829
+ }
830
+ analysis = analyze_intake(payload)
831
+ topology = decide_topology(analysis, topology_choice)
832
+ vital = extract_vital_structure(analysis, topology)
833
+ reasoning = select_reasoning_architecture(analysis, topology, selected_layers or [])
834
+ pack = generate_prompt_pack(analysis, topology, vital, reasoning, payload)
835
+ qa = qa_repair_pass(pack)
836
+ final = assemble_final_output(analysis, topology, vital, reasoning, qa)
837
+
838
+ metrics_html = render_metrics(final.get("metrics", {}))
839
+ architecture_md = "```json\n" + json_text(final.get("architecture_analysis", {})) + "\n```"
840
+ prompt_pack_text = clean_text(final.get("prompt_pack"), 120000)
841
+ execution_md = render_list(final.get("execution_plan", []))
842
+ qa_md = render_qa(final.get("qa_checklist", {}), final.get("repair_protocol", []))
843
+ runtime_md = render_runtime(_RUNTIME_TRACE)
844
+ return metrics_html, architecture_md, prompt_pack_text, execution_md, qa_md, runtime_md
845
+
846
+
847
+ def render_metrics(metrics: dict[str, Any]) -> str:
848
+ cards = []
849
+ for label in ["Prompt Integrity", "Context Coverage", "Agent Readiness", "Risk Control"]:
850
+ try:
851
+ score = max(0, min(100, int(metrics.get(label, 0))))
852
+ except (TypeError, ValueError):
853
+ score = 0
854
+ cards.append(
855
+ f'<div class="metric-card"><span>{label}</span><strong>{score}</strong>'
856
+ f'<div class="metric-track"><i style="width:{score}%"></i></div></div>'
857
+ )
858
+ return '<div class="metrics-bar">' + "".join(cards) + "</div>"
859
+
860
+
861
+ def render_list(items: Any) -> str:
862
+ values = clean_list(items, 30)
863
+ if not values:
864
+ return "No execution steps were produced."
865
+ return "\n".join(f"{index}. {item}" for index, item in enumerate(values, start=1))
866
+
867
+
868
+ def render_qa(checks: Any, repair_protocol: Any) -> str:
869
+ lines = ["### QA Checklist"]
870
+ if isinstance(checks, dict):
871
+ for label, passed in checks.items():
872
+ lines.append(f"- [{'x' if passed else ' '}] {label.replace('_', ' ').title()}")
873
+ lines.append("\n### Repair Protocol")
874
+ lines.extend(f"{index}. {item}" for index, item in enumerate(clean_list(repair_protocol, 20), start=1))
875
+ return "\n".join(lines)
876
+
877
+
878
+ def render_runtime(trace: list[dict[str, Any]]) -> str:
879
+ lines = [
880
+ "| Stage | Source | Model | Time | Note |",
881
+ "|---|---|---|---:|---|",
882
+ ]
883
+ for row in trace:
884
+ note = clean_text(row.get("note"), 240).replace("|", "/")
885
+ lines.append(
886
+ f"| `{row.get('stage')}` | `{row.get('source')}` | `{row.get('model_id')}` | "
887
+ f"{row.get('elapsed_ms')} ms | {note} |"
888
+ )
889
+ fallback_stages = [row["stage"] for row in trace if row.get("source") == "deterministic_fallback"]
890
+ lines.append(
891
+ "\n**Fallback stages:** "
892
+ + (", ".join(f"`{stage}`" for stage in fallback_stages) if fallback_stages else "None")
893
+ )
894
+ return "\n".join(lines)
895
+
896
+
897
+ def load_example() -> tuple[Any, ...]:
898
+ return (
899
+ "Build a privacy-first issue triage agent that turns raw bug reports into prioritized engineering tickets.",
900
+ "Small product engineering teams",
901
+ "A working agent workflow with prompts, handoffs, and acceptance tests",
902
+ "Auto",
903
+ "High",
904
+ "English",
905
+ ["CRAFT", "Kahneman System 2", "Pareto 80/20", "Agentic Loop", "Private CoT", "Self-Correction", "Sentinel Recovery"],
906
+ "The user can provide incomplete reports and may not know technical terminology.",
907
+ "The product must reduce triage time without hiding uncertainty.",
908
+ "Python, GitHub Issues, structured JSON handoffs, no mandatory cloud API.",
909
+ "Never invent reproduction evidence. Keep private reasoning internal.",
910
+ "Bug report text, logs, screenshots, repository metadata.",
911
+ "Prioritized ticket with severity, confidence, assumptions, reproduction steps, owner suggestion, and verification checklist.",
912
+ "Hallucinated root cause; wrong severity; missing evidence; duplicate issue.",
913
+ "All required ticket fields exist; severity is evidence-backed; uncertain claims are labeled; duplicate check completed.",
914
+ )
915
+
916
+
917
+ def build_demo() -> Any:
918
+ import gradio as gr
919
+
920
+ css_path = os.path.join(os.path.dirname(__file__), "assets", "style.css")
921
+ css = ""
922
+ if os.path.exists(css_path):
923
+ with open(css_path, "r", encoding="utf-8") as handle:
924
+ css = handle.read()
925
+
926
+ with gr.Blocks(title=APP_TITLE, css=css) as demo:
927
+ gr.HTML(
928
+ f"""
929
+ <section class="forge-hero">
930
+ <div class="hero-kicker">Multi-call small-model pipeline</div>
931
+ <h1>{APP_TITLE}</h1>
932
+ <p>{APP_SUBTITLE}. Turn messy software, app, and agent ideas into executable prompt architectures.</p>
933
+ <div class="hero-badges"><span>7 isolated calls</span><span>Stage-level fallback</span><span>Private reasoning</span><span>Compiler, not generator</span></div>
934
+ </section>
935
+ """
936
+ )
937
+ with gr.Row(elem_classes=["forge-layout"]):
938
+ with gr.Column(scale=1, elem_classes=["config-panel"]):
939
+ gr.HTML('<div class="panel-title">Compiler Input</div>')
940
+ project_idea = gr.Textbox(label="Project idea", lines=4, placeholder="Describe the rough idea to compile...")
941
+ with gr.Row():
942
+ target_user = gr.Textbox(label="Target user")
943
+ build_target = gr.Textbox(label="Build target")
944
+ with gr.Row():
945
+ topology_choice = gr.Dropdown(TOPOLOGIES, value="Auto", label="Topology")
946
+ risk_level = gr.Dropdown(["Low", "Medium", "High", "Critical"], value="Medium", label="Risk level")
947
+ output_language = gr.Textbox(value="English", label="Output language")
948
+ selected_layers = gr.CheckboxGroup(REASONING_LAYERS, value=["CRAFT", "Pareto 80/20", "Private CoT", "Self-Correction", "Sentinel Recovery"], label="Reasoning layers")
949
+ with gr.Accordion("Context inputs", open=False):
950
+ user_context = gr.Textbox(label="User context", lines=3)
951
+ project_context = gr.Textbox(label="Project context", lines=3)
952
+ technical_context = gr.Textbox(label="Technical context", lines=3)
953
+ constraints = gr.Textbox(label="Constraints", lines=3)
954
+ inputs_files = gr.Textbox(label="Inputs / files", lines=3)
955
+ with gr.Accordion("Contracts and controls", open=True):
956
+ output_contract = gr.Textbox(label="Output contract", lines=3)
957
+ failure_modes = gr.Textbox(label="Failure modes", lines=3)
958
+ verification_criteria = gr.Textbox(label="Verification criteria", lines=3)
959
+ with gr.Row():
960
+ compile_button = gr.Button("Compile Architecture", variant="primary")
961
+ example_button = gr.Button("Load Example", variant="secondary")
962
+
963
+ with gr.Column(scale=1, elem_classes=["output-panel"]):
964
+ metrics = gr.HTML(value=render_metrics({}))
965
+ gr.HTML('<div class="panel-title">Compiled Output</div>')
966
+ with gr.Accordion("Prompt Pack", open=True):
967
+ prompt_output = gr.Code(label="Copyable compiled prompt pack", language="markdown", lines=28)
968
+ with gr.Accordion("Architecture Analysis", open=False):
969
+ architecture_output = gr.Markdown()
970
+ with gr.Accordion("Execution Plan", open=False):
971
+ execution_output = gr.Markdown()
972
+ with gr.Accordion("QA / Repair Protocol", open=False):
973
+ qa_output = gr.Markdown()
974
+ with gr.Accordion("Runtime Details", open=False):
975
+ runtime_output = gr.Markdown()
976
+
977
+ inputs = [
978
+ project_idea,
979
+ target_user,
980
+ build_target,
981
+ topology_choice,
982
+ risk_level,
983
+ output_language,
984
+ selected_layers,
985
+ user_context,
986
+ project_context,
987
+ technical_context,
988
+ constraints,
989
+ inputs_files,
990
+ output_contract,
991
+ failure_modes,
992
+ verification_criteria,
993
+ ]
994
+ compile_button.click(
995
+ fn=compile_context,
996
+ inputs=inputs,
997
+ outputs=[metrics, architecture_output, prompt_output, execution_output, qa_output, runtime_output],
998
+ )
999
+ example_button.click(fn=load_example, inputs=[], outputs=inputs)
1000
+ return demo
1001
+
1002
+
1003
+ demo = None if parse_bool_env("CONTEXTFORGE_SKIP_UI_BUILD", False) else build_demo()
1004
+
1005
+
1006
+ if __name__ == "__main__":
1007
+ (demo or build_demo()).launch()
assets/style.css ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --bg: #080b11;
3
+ --panel: #0d121b;
4
+ --panel-2: #111925;
5
+ --line: rgba(129, 159, 190, 0.24);
6
+ --text: #e9f0f7;
7
+ --muted: #91a2b5;
8
+ --cyan: #5ad5d9;
9
+ --blue: #5489ff;
10
+ --green: #74d69c;
11
+ --amber: #f2bd63;
12
+ }
13
+
14
+ body,
15
+ .gradio-container {
16
+ background: var(--bg) !important;
17
+ color: var(--text) !important;
18
+ }
19
+
20
+ .gradio-container {
21
+ width: min(100%, 1480px) !important;
22
+ max-width: 1480px !important;
23
+ margin: 0 auto !important;
24
+ padding: 22px !important;
25
+ --body-background-fill: var(--bg);
26
+ --body-text-color: var(--text);
27
+ --body-text-color-subdued: var(--muted);
28
+ --background-fill-primary: var(--panel);
29
+ --background-fill-secondary: var(--panel-2);
30
+ --block-background-fill: var(--panel);
31
+ --block-border-color: var(--line);
32
+ --input-background-fill: #0a1018;
33
+ --input-border-color: rgba(129, 159, 190, 0.34);
34
+ --button-primary-background-fill: var(--blue);
35
+ --button-primary-background-fill-hover: #6c9bff;
36
+ }
37
+
38
+ .forge-hero {
39
+ border: 1px solid var(--line);
40
+ border-radius: 16px;
41
+ background:
42
+ radial-gradient(circle at 78% 12%, rgba(84, 137, 255, 0.18), transparent 28%),
43
+ linear-gradient(135deg, #0e1520, #090d14);
44
+ padding: 30px;
45
+ box-shadow: 0 20px 70px rgba(0, 0, 0, 0.32);
46
+ }
47
+
48
+ .hero-kicker,
49
+ .panel-title {
50
+ color: var(--cyan);
51
+ font-size: 0.76rem;
52
+ font-weight: 800;
53
+ letter-spacing: 0.13em;
54
+ text-transform: uppercase;
55
+ }
56
+
57
+ .forge-hero h1 {
58
+ color: var(--text);
59
+ font-size: clamp(2.5rem, 6vw, 4.8rem);
60
+ letter-spacing: -0.06em;
61
+ line-height: 0.94;
62
+ margin: 12px 0;
63
+ }
64
+
65
+ .forge-hero p {
66
+ color: #c3d0dd;
67
+ font-size: 1.08rem;
68
+ line-height: 1.55;
69
+ margin: 0;
70
+ max-width: 760px;
71
+ }
72
+
73
+ .hero-badges {
74
+ display: flex;
75
+ flex-wrap: wrap;
76
+ gap: 8px;
77
+ margin-top: 18px;
78
+ }
79
+
80
+ .hero-badges span {
81
+ border: 1px solid rgba(90, 213, 217, 0.25);
82
+ border-radius: 999px;
83
+ background: rgba(90, 213, 217, 0.06);
84
+ color: #bdeef0;
85
+ padding: 6px 10px;
86
+ font-size: 0.8rem;
87
+ }
88
+
89
+ .forge-layout {
90
+ display: grid !important;
91
+ grid-template-columns: minmax(420px, 0.88fr) minmax(520px, 1.12fr);
92
+ align-items: start;
93
+ gap: 18px;
94
+ margin-top: 18px;
95
+ }
96
+
97
+ .config-panel,
98
+ .output-panel {
99
+ border: 1px solid var(--line);
100
+ border-radius: 14px;
101
+ background: linear-gradient(180deg, rgba(17, 25, 37, 0.98), rgba(10, 15, 23, 0.98));
102
+ min-width: 0;
103
+ padding: 16px;
104
+ }
105
+
106
+ .output-panel {
107
+ position: sticky;
108
+ top: 14px;
109
+ }
110
+
111
+ .panel-title {
112
+ margin: 2px 0 12px;
113
+ }
114
+
115
+ .gradio-container .block,
116
+ .gradio-container .form,
117
+ .gradio-container .wrap,
118
+ .gradio-container .container,
119
+ .gradio-container details,
120
+ .gradio-container button[aria-expanded] {
121
+ border-color: var(--line) !important;
122
+ background: rgba(13, 18, 27, 0.9) !important;
123
+ color: var(--text) !important;
124
+ }
125
+
126
+ .gradio-container label,
127
+ .gradio-container span,
128
+ .gradio-container .prose,
129
+ .gradio-container .prose * {
130
+ color: var(--text) !important;
131
+ }
132
+
133
+ .gradio-container input,
134
+ .gradio-container textarea,
135
+ .gradio-container select,
136
+ .gradio-container [role="listbox"],
137
+ .gradio-container [role="combobox"] {
138
+ border-color: rgba(129, 159, 190, 0.34) !important;
139
+ background: #091019 !important;
140
+ color: var(--text) !important;
141
+ }
142
+
143
+ .gradio-container input:focus,
144
+ .gradio-container textarea:focus {
145
+ border-color: var(--cyan) !important;
146
+ box-shadow: 0 0 0 2px rgba(90, 213, 217, 0.13) !important;
147
+ }
148
+
149
+ .gradio-container button.primary {
150
+ border: 1px solid rgba(255, 255, 255, 0.2) !important;
151
+ border-radius: 10px !important;
152
+ background: linear-gradient(135deg, var(--blue), #6764e8) !important;
153
+ color: white !important;
154
+ font-weight: 800 !important;
155
+ }
156
+
157
+ .metrics-bar {
158
+ display: grid;
159
+ grid-template-columns: repeat(4, minmax(0, 1fr));
160
+ gap: 8px;
161
+ margin-bottom: 12px;
162
+ }
163
+
164
+ .metric-card {
165
+ border: 1px solid var(--line);
166
+ border-radius: 10px;
167
+ background: rgba(8, 13, 21, 0.82);
168
+ padding: 10px;
169
+ }
170
+
171
+ .metric-card span {
172
+ color: var(--muted) !important;
173
+ display: block;
174
+ font-size: 0.72rem;
175
+ line-height: 1.2;
176
+ min-height: 28px;
177
+ }
178
+
179
+ .metric-card strong {
180
+ color: var(--text);
181
+ display: block;
182
+ font-size: 1.45rem;
183
+ margin: 4px 0 7px;
184
+ }
185
+
186
+ .metric-track {
187
+ border-radius: 999px;
188
+ background: #182231;
189
+ height: 4px;
190
+ overflow: hidden;
191
+ }
192
+
193
+ .metric-track i {
194
+ background: linear-gradient(90deg, var(--cyan), var(--green));
195
+ display: block;
196
+ height: 100%;
197
+ }
198
+
199
+ .output-panel textarea {
200
+ font-family: "Cascadia Code", "SFMono-Regular", Consolas, monospace !important;
201
+ font-size: 0.82rem !important;
202
+ line-height: 1.55 !important;
203
+ }
204
+
205
+ .gradio-container footer {
206
+ display: none !important;
207
+ }
208
+
209
+ @media (max-width: 980px) {
210
+ .forge-layout {
211
+ grid-template-columns: 1fr;
212
+ }
213
+
214
+ .output-panel {
215
+ position: static;
216
+ }
217
+ }
218
+
219
+ @media (max-width: 620px) {
220
+ .gradio-container {
221
+ padding: 12px !important;
222
+ }
223
+
224
+ .forge-hero {
225
+ padding: 20px;
226
+ }
227
+
228
+ .metrics-bar {
229
+ grid-template-columns: repeat(2, minmax(0, 1fr));
230
+ }
231
+ }
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ gradio>=4.44,<6
2
+ transformers>=4.44,<5
3
+ torch>=2.2
4
+ accelerate>=0.33
test_contextforge.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import os
4
+
5
+ os.environ["CONTEXTFORGE_ENABLE_MODEL"] = "0"
6
+ os.environ["CONTEXTFORGE_SKIP_UI_BUILD"] = "1"
7
+
8
+ import app
9
+
10
+
11
+ BASE = {
12
+ "project_idea": "Build an issue triage agent.",
13
+ "target_user": "Engineering teams",
14
+ "build_target": "Agent workflow",
15
+ "risk_level": "High",
16
+ "output_language": "English",
17
+ "user_context": "Reports may be incomplete.",
18
+ "project_context": "Reduce triage time.",
19
+ "technical_context": "Python and structured JSON.",
20
+ "constraints": "Do not invent evidence.",
21
+ "inputs_files": "Bug reports and logs.",
22
+ "output_contract": "Return a prioritized ticket with evidence.",
23
+ "failure_modes": "Hallucinated root cause.",
24
+ "verification_criteria": "All ticket fields and evidence exist.",
25
+ }
26
+
27
+
28
+ def compile_for(topology: str) -> tuple[str, str, str, str, str, str]:
29
+ return app.compile_context(
30
+ BASE["project_idea"],
31
+ BASE["target_user"],
32
+ BASE["build_target"],
33
+ topology,
34
+ BASE["risk_level"],
35
+ BASE["output_language"],
36
+ app.REASONING_LAYERS,
37
+ BASE["user_context"],
38
+ BASE["project_context"],
39
+ BASE["technical_context"],
40
+ BASE["constraints"],
41
+ BASE["inputs_files"],
42
+ BASE["output_contract"],
43
+ BASE["failure_modes"],
44
+ BASE["verification_criteria"],
45
+ )
46
+
47
+
48
+ def main() -> None:
49
+ analysis = app.analyze_intake(BASE)
50
+ topology = app.decide_topology(analysis, "Cascade")
51
+ vital = app.extract_vital_structure(analysis, topology)
52
+ reasoning = app.select_reasoning_architecture(analysis, topology, app.REASONING_LAYERS)
53
+ pack = app.generate_prompt_pack(analysis, topology, vital, reasoning, BASE)
54
+ qa = app.qa_repair_pass(pack)
55
+ final = app.assemble_final_output(analysis, topology, vital, reasoning, qa)
56
+ assert qa["pass"]
57
+ assert final["prompt_pack"]
58
+
59
+ expected_counts = {
60
+ "Single Prompt": 1,
61
+ "Cascade": 4,
62
+ "Context Pack": 2,
63
+ "Agent Workflow": 4,
64
+ }
65
+ for topology_name, expected_count in expected_counts.items():
66
+ _, _, prompt_text, _, qa_text, runtime = compile_for(topology_name)
67
+ assert prompt_text.count("[ROLE]") == expected_count
68
+ for tag in app.REQUIRED_PROMPT_TAGS:
69
+ assert prompt_text.count(f"[{tag}]") == expected_count
70
+ assert "reveal your chain of thought" not in prompt_text.lower()
71
+ assert "strategy | upside | risk | cost | selected" in prompt_text
72
+ assert "No Chain Of Thought Leakage" in qa_text
73
+ assert runtime.count("deterministic_fallback") >= 7
74
+
75
+ print("ContextForge QA passed.")
76
+
77
+
78
+ if __name__ == "__main__":
79
+ main()