RthItalia commited on
Commit
acd5491
·
verified ·
1 Parent(s): 75b79d0

Polish Backyard AI experience with Codex

Browse files
Files changed (4) hide show
  1. README.md +9 -0
  2. app.py +55 -15
  3. assets/style.css +68 -0
  4. test_contextforge.py +7 -0
README.md CHANGED
@@ -19,6 +19,15 @@ ContextForge compiles messy software, app, and agent ideas into executable promp
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
 
19
 
20
  **Backup Gradio Space:** https://huggingface.co/spaces/RthItalia/ContextForge
21
 
22
+ **Tagline:** From fuzzy brief to build-ready agent blueprint.
23
+
24
+ ## Backyard AI Fit
25
+
26
+ - Built for real builders using AI coding agents.
27
+ - Real problem: vague briefs make Codex and other agents produce wrong code, generic UI, or incomplete workflows.
28
+ - Real use evidence: this architecture was used to coordinate Trollsona development, including UI refactor, model cascade, QA, packaging, and video automation.
29
+ - Small-model fit: ContextForge decomposes a hard prompt-writing task into seven smaller calls so a small model can handle it.
30
+
31
  The backend always executes seven isolated modules sequentially:
32
 
33
  1. intake analysis
app.py CHANGED
@@ -10,7 +10,7 @@ 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"
@@ -93,8 +93,8 @@ class StageResult:
93
  "stage": stage,
94
  "source": self.source,
95
  "model_id": self.model_id,
96
- "elapsed_ms": self.elapsed_ms,
97
- "note": self.note,
98
  }
99
 
100
 
@@ -856,6 +856,12 @@ def compile_context(
856
  def render_metrics(metrics: dict[str, Any]) -> str:
857
  cards = []
858
  for label in ["Prompt Integrity", "Context Coverage", "Agent Readiness", "Risk Control"]:
 
 
 
 
 
 
859
  try:
860
  score = max(0, min(100, int(metrics.get(label, 0))))
861
  except (TypeError, ValueError):
@@ -886,14 +892,14 @@ def render_qa(checks: Any, repair_protocol: Any) -> str:
886
 
887
  def render_runtime(trace: list[dict[str, Any]]) -> str:
888
  lines = [
889
- "| Stage | Source | Model | Time | Note |",
890
- "|---|---|---|---:|---|",
891
  ]
892
  for row in trace:
893
- note = clean_text(row.get("note"), 240).replace("|", "/")
894
  lines.append(
895
- f"| `{row.get('stage')}` | `{row.get('source')}` | `{row.get('model_id')}` | "
896
- f"{row.get('elapsed_ms')} ms | {note} |"
897
  )
898
  fallback_stages = [row["stage"] for row in trace if row.get("source") == "deterministic_fallback"]
899
  lines.append(
@@ -903,6 +909,13 @@ def render_runtime(trace: list[dict[str, Any]]) -> str:
903
  return "\n".join(lines)
904
 
905
 
 
 
 
 
 
 
 
906
  def load_example() -> tuple[Any, ...]:
907
  return (
908
  "Build a privacy-first issue triage agent that turns raw bug reports into prioritized engineering tickets.",
@@ -938,15 +951,32 @@ def build_demo() -> Any:
938
  <section class="forge-hero">
939
  <div class="hero-kicker">Multi-call small-model pipeline</div>
940
  <h1>{APP_TITLE}</h1>
941
- <p>{APP_SUBTITLE}. Turn messy software, app, and agent ideas into executable prompt architectures.</p>
 
942
  <div class="hero-badges"><span>7 isolated calls</span><span>Stage-level fallback</span><span>Private reasoning</span><span>Compiler, not generator</span></div>
943
  </section>
 
 
 
944
  """
945
  )
946
  with gr.Row(elem_classes=["forge-layout"]):
947
  with gr.Column(scale=1, elem_classes=["config-panel"]):
948
  gr.HTML('<div class="panel-title">Compiler Input</div>')
949
- project_idea = gr.Textbox(label="Project idea", lines=4, placeholder="Describe the rough idea to compile...")
 
 
 
 
 
 
 
 
 
 
 
 
 
950
  with gr.Row():
951
  target_user = gr.Textbox(label="Target user")
952
  build_target = gr.Textbox(label="Build target")
@@ -954,26 +984,31 @@ def build_demo() -> Any:
954
  topology_choice = gr.Dropdown(TOPOLOGIES, value="Auto", label="Topology")
955
  risk_level = gr.Dropdown(["Low", "Medium", "High", "Critical"], value="Medium", label="Risk level")
956
  output_language = gr.Textbox(value="English", label="Output language")
957
- selected_layers = gr.CheckboxGroup(REASONING_LAYERS, value=["CRAFT", "Pareto 80/20", "Private CoT", "Self-Correction", "Sentinel Recovery"], label="Reasoning layers")
958
- with gr.Accordion("Context inputs", open=False):
959
  user_context = gr.Textbox(label="User context", lines=3)
960
  project_context = gr.Textbox(label="Project context", lines=3)
961
  technical_context = gr.Textbox(label="Technical context", lines=3)
962
  constraints = gr.Textbox(label="Constraints", lines=3)
963
  inputs_files = gr.Textbox(label="Inputs / files", lines=3)
964
- with gr.Accordion("Contracts and controls", open=True):
965
  output_contract = gr.Textbox(label="Output contract", lines=3)
966
  failure_modes = gr.Textbox(label="Failure modes", lines=3)
967
  verification_criteria = gr.Textbox(label="Verification criteria", lines=3)
968
  with gr.Row():
969
- compile_button = gr.Button("Compile Architecture", variant="primary")
970
  example_button = gr.Button("Load Example", variant="secondary")
971
 
972
  with gr.Column(scale=1, elem_classes=["output-panel"]):
973
  metrics = gr.HTML(value=render_metrics({}))
974
  gr.HTML('<div class="panel-title">Compiled Output</div>')
975
  with gr.Accordion("Prompt Pack", open=True):
976
- prompt_output = gr.Code(label="Copyable compiled prompt pack", language="markdown", lines=28)
 
 
 
 
 
977
  with gr.Accordion("Architecture Analysis", open=False):
978
  architecture_output = gr.Markdown()
979
  with gr.Accordion("Execution Plan", open=False):
@@ -1005,6 +1040,11 @@ def build_demo() -> Any:
1005
  inputs=inputs,
1006
  outputs=[metrics, architecture_output, prompt_output, execution_output, qa_output, runtime_output],
1007
  )
 
 
 
 
 
1008
  example_button.click(fn=load_example, inputs=[], outputs=inputs)
1009
  return demo
1010
 
 
10
 
11
 
12
  APP_TITLE = "ContextForge"
13
+ APP_SUBTITLE = "From fuzzy brief to build-ready agent blueprint."
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"
 
93
  "stage": stage,
94
  "source": self.source,
95
  "model_id": self.model_id,
96
+ "fallback_reason": self.note if self.source == "deterministic_fallback" else "",
97
+ "duration_ms": self.elapsed_ms,
98
  }
99
 
100
 
 
856
  def render_metrics(metrics: dict[str, Any]) -> str:
857
  cards = []
858
  for label in ["Prompt Integrity", "Context Coverage", "Agent Readiness", "Risk Control"]:
859
+ if label not in metrics:
860
+ cards.append(
861
+ f'<div class="metric-card metric-pending"><span>{label}</span><strong>—</strong>'
862
+ '<div class="metric-track"><i style="width:0%"></i></div><small>pending</small></div>'
863
+ )
864
+ continue
865
  try:
866
  score = max(0, min(100, int(metrics.get(label, 0))))
867
  except (TypeError, ValueError):
 
892
 
893
  def render_runtime(trace: list[dict[str, Any]]) -> str:
894
  lines = [
895
+ "| Stage | Source | Fallback reason | Duration ms |",
896
+ "|---|---|---|---:|",
897
  ]
898
  for row in trace:
899
+ fallback_reason = clean_text(row.get("fallback_reason"), 240).replace("|", "/") or "—"
900
  lines.append(
901
+ f"| `{row.get('stage')}` | `{row.get('source')}` | {fallback_reason} | "
902
+ f"{row.get('duration_ms')} |"
903
  )
904
  fallback_stages = [row["stage"] for row in trace if row.get("source") == "deterministic_fallback"]
905
  lines.append(
 
909
  return "\n".join(lines)
910
 
911
 
912
+ def update_mode(mode: str) -> tuple[Any, Any]:
913
+ import gradio as gr
914
+
915
+ show_full_control = mode == "Full Control"
916
+ return gr.update(visible=show_full_control), gr.update(visible=show_full_control)
917
+
918
+
919
  def load_example() -> tuple[Any, ...]:
920
  return (
921
  "Build a privacy-first issue triage agent that turns raw bug reports into prioritized engineering tickets.",
 
951
  <section class="forge-hero">
952
  <div class="hero-kicker">Multi-call small-model pipeline</div>
953
  <h1>{APP_TITLE}</h1>
954
+ <p class="hero-tagline">{APP_SUBTITLE}</p>
955
+ <p class="hero-description">ContextForge turns messy software, app, and agent ideas into executable prompt architectures.</p>
956
  <div class="hero-badges"><span>7 isolated calls</span><span>Stage-level fallback</span><span>Private reasoning</span><span>Compiler, not generator</span></div>
957
  </section>
958
+ <section class="pipeline-strip" aria-label="ContextForge seven-stage pipeline">
959
+ <span>Intake</span><b>→</b><span>Topology</span><b>→</b><span>Vital Structure</span><b>→</b><span>Reasoning</span><b>→</b><span>Prompt Pack</span><b>→</b><span>QA Repair</span><b>→</b><span>Assembly</span>
960
+ </section>
961
  """
962
  )
963
  with gr.Row(elem_classes=["forge-layout"]):
964
  with gr.Column(scale=1, elem_classes=["config-panel"]):
965
  gr.HTML('<div class="panel-title">Compiler Input</div>')
966
+ mode = gr.Radio(
967
+ ["Fast Compile", "Full Control"],
968
+ value="Fast Compile",
969
+ label="Compile mode",
970
+ elem_classes=["mode-toggle"],
971
+ )
972
+ gr.HTML(
973
+ '<p class="project-helper">Paste a rough app, agent or workflow idea. ContextForge compiles it into a staged prompt pack for Codex or another coding agent.</p>'
974
+ )
975
+ project_idea = gr.Textbox(
976
+ label="Project idea",
977
+ lines=4,
978
+ placeholder="Example: I want to build a Gradio app that helps students prepare oral exams from a syllabus.",
979
+ )
980
  with gr.Row():
981
  target_user = gr.Textbox(label="Target user")
982
  build_target = gr.Textbox(label="Build target")
 
984
  topology_choice = gr.Dropdown(TOPOLOGIES, value="Auto", label="Topology")
985
  risk_level = gr.Dropdown(["Low", "Medium", "High", "Critical"], value="Medium", label="Risk level")
986
  output_language = gr.Textbox(value="English", label="Output language")
987
+ selected_layers = gr.CheckboxGroup(REASONING_LAYERS, value=["CRAFT", "Pareto 80/20", "Private CoT", "Self-Correction", "Sentinel Recovery"], label="Cognitive modules")
988
+ with gr.Accordion("Context inputs", open=False, visible=False) as context_inputs_accordion:
989
  user_context = gr.Textbox(label="User context", lines=3)
990
  project_context = gr.Textbox(label="Project context", lines=3)
991
  technical_context = gr.Textbox(label="Technical context", lines=3)
992
  constraints = gr.Textbox(label="Constraints", lines=3)
993
  inputs_files = gr.Textbox(label="Inputs / files", lines=3)
994
+ with gr.Accordion("Contracts and controls", open=False, visible=False) as contracts_accordion:
995
  output_contract = gr.Textbox(label="Output contract", lines=3)
996
  failure_modes = gr.Textbox(label="Failure modes", lines=3)
997
  verification_criteria = gr.Textbox(label="Verification criteria", lines=3)
998
  with gr.Row():
999
+ compile_button = gr.Button("Compile Prompt Architecture", variant="primary")
1000
  example_button = gr.Button("Load Example", variant="secondary")
1001
 
1002
  with gr.Column(scale=1, elem_classes=["output-panel"]):
1003
  metrics = gr.HTML(value=render_metrics({}))
1004
  gr.HTML('<div class="panel-title">Compiled Output</div>')
1005
  with gr.Accordion("Prompt Pack", open=True):
1006
+ prompt_output = gr.Code(
1007
+ value="No architecture compiled yet. Fill the project idea and run Compile Prompt Architecture.",
1008
+ label="Copyable compiled prompt pack",
1009
+ language="markdown",
1010
+ lines=28,
1011
+ )
1012
  with gr.Accordion("Architecture Analysis", open=False):
1013
  architecture_output = gr.Markdown()
1014
  with gr.Accordion("Execution Plan", open=False):
 
1040
  inputs=inputs,
1041
  outputs=[metrics, architecture_output, prompt_output, execution_output, qa_output, runtime_output],
1042
  )
1043
+ mode.change(
1044
+ fn=update_mode,
1045
+ inputs=[mode],
1046
+ outputs=[context_inputs_accordion, contracts_accordion],
1047
+ )
1048
  example_button.click(fn=load_example, inputs=[], outputs=inputs)
1049
  return demo
1050
 
assets/style.css CHANGED
@@ -70,6 +70,18 @@ body,
70
  max-width: 760px;
71
  }
72
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  .hero-badges {
74
  display: flex;
75
  flex-wrap: wrap;
@@ -86,6 +98,35 @@ body,
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);
@@ -112,6 +153,21 @@ body,
112
  margin: 2px 0 12px;
113
  }
114
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  .gradio-container .block,
116
  .gradio-container .form,
117
  .gradio-container .wrap,
@@ -183,6 +239,18 @@ body,
183
  margin: 4px 0 7px;
184
  }
185
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  .metric-track {
187
  border-radius: 999px;
188
  background: #182231;
 
70
  max-width: 760px;
71
  }
72
 
73
+ .forge-hero .hero-tagline {
74
+ color: var(--text);
75
+ font-size: 1.24rem;
76
+ font-weight: 750;
77
+ margin-bottom: 5px;
78
+ }
79
+
80
+ .forge-hero .hero-description {
81
+ color: #aab9c8;
82
+ font-size: 0.98rem;
83
+ }
84
+
85
  .hero-badges {
86
  display: flex;
87
  flex-wrap: wrap;
 
98
  font-size: 0.8rem;
99
  }
100
 
101
+ .pipeline-strip {
102
+ border: 1px solid var(--line);
103
+ border-radius: 12px;
104
+ background: rgba(13, 18, 27, 0.92);
105
+ display: flex;
106
+ align-items: center;
107
+ gap: 8px;
108
+ margin-top: 12px;
109
+ overflow-x: auto;
110
+ padding: 10px 12px;
111
+ scrollbar-width: thin;
112
+ }
113
+
114
+ .pipeline-strip span {
115
+ border: 1px solid rgba(90, 213, 217, 0.2);
116
+ border-radius: 999px;
117
+ background: rgba(90, 213, 217, 0.055);
118
+ color: #c8f1f2;
119
+ flex: 0 0 auto;
120
+ font-size: 0.74rem;
121
+ font-weight: 750;
122
+ padding: 6px 9px;
123
+ }
124
+
125
+ .pipeline-strip b {
126
+ color: var(--blue);
127
+ font-size: 0.78rem;
128
+ }
129
+
130
  .forge-layout {
131
  display: grid !important;
132
  grid-template-columns: minmax(420px, 0.88fr) minmax(520px, 1.12fr);
 
153
  margin: 2px 0 12px;
154
  }
155
 
156
+ .project-helper {
157
+ border-left: 2px solid var(--cyan);
158
+ color: #aec0d1;
159
+ font-size: 0.86rem;
160
+ line-height: 1.45;
161
+ margin: 4px 0 10px;
162
+ padding-left: 10px;
163
+ }
164
+
165
+ .mode-toggle {
166
+ border: 1px solid rgba(90, 213, 217, 0.18) !important;
167
+ border-radius: 10px !important;
168
+ background: rgba(8, 13, 21, 0.55) !important;
169
+ }
170
+
171
  .gradio-container .block,
172
  .gradio-container .form,
173
  .gradio-container .wrap,
 
239
  margin: 4px 0 7px;
240
  }
241
 
242
+ .metric-card small {
243
+ color: var(--muted);
244
+ display: block;
245
+ font-size: 0.64rem;
246
+ margin-top: 5px;
247
+ text-transform: uppercase;
248
+ }
249
+
250
+ .metric-pending strong {
251
+ color: var(--muted);
252
+ }
253
+
254
  .metric-track {
255
  border-radius: 999px;
256
  background: #182231;
test_contextforge.py CHANGED
@@ -46,6 +46,12 @@ def compile_for(topology: str) -> tuple[str, str, str, str, str, str]:
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)
@@ -71,6 +77,7 @@ def main() -> None:
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
 
 
46
 
47
 
48
  def main() -> None:
49
+ assert "pending" in app.render_metrics({}).lower()
50
+ fast_updates = app.update_mode("Fast Compile")
51
+ full_updates = app.update_mode("Full Control")
52
+ assert all(update.get("visible") is False for update in fast_updates)
53
+ assert all(update.get("visible") is True for update in full_updates)
54
+
55
  analysis = app.analyze_intake(BASE)
56
  topology = app.decide_topology(analysis, "Cascade")
57
  vital = app.extract_vital_structure(analysis, topology)
 
77
  assert "strategy | upside | risk | cost | selected" in prompt_text
78
  assert "No Chain Of Thought Leakage" in qa_text
79
  assert runtime.count("deterministic_fallback") >= 7
80
+ assert "| Stage | Source | Fallback reason | Duration ms |" in runtime
81
 
82
  print("ContextForge QA passed.")
83