Executor-Tyrant-Framework Claude Sonnet 4.6 commited on
Commit
bfc60f2
Β·
1 Parent(s): 0bce5fd

Fix dict iteration crash in neuro_foundation + harden QB spec workflow

Browse files

neuro_foundation.py: snapshot self.synapses before iteration in step()
and _prune_synapses() β€” concurrent writes were causing RuntimeError on
dictionary changed size during iteration.

system_prompt.py: Step 1 now explicitly blocks Step 2 (no exceptions);
Step 2 grep template adds --exclude-dir=venv --exclude-dir=.git to
prevent 60s timeout scanning venv/. Both issues observed in QB #126 run.

app.py: defensive list() copies for history/pending_proposals state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Files changed (3) hide show
  1. app.py +2 -2
  2. neuro_foundation.py +2 -2
  3. system_prompt.py +12 -4
app.py CHANGED
@@ -341,8 +341,8 @@ def _build_api_messages(history: list, system_prompt: str) -> list:
341
  # ---------------------------------------------------------------------------
342
 
343
  def agent_loop(message: str, history: list, pending_proposals: list, uploaded_file) -> tuple:
344
- safe_hist = history or []
345
- safe_props = pending_proposals or []
346
 
347
  if not message.strip() and uploaded_file is None:
348
  return (safe_hist, "", safe_props, _format_gate_choices(safe_props),
 
341
  # ---------------------------------------------------------------------------
342
 
343
  def agent_loop(message: str, history: list, pending_proposals: list, uploaded_file) -> tuple:
344
+ safe_hist = list(history or [])
345
+ safe_props = list(pending_proposals or [])
346
 
347
  if not message.strip() and uploaded_file is None:
348
  return (safe_hist, "", safe_props, _format_gate_choices(safe_props),
neuro_foundation.py CHANGED
@@ -1893,7 +1893,7 @@ class Graph:
1893
  if self.config.get("three_factor_enabled", False):
1894
  trace_tau = self.config["eligibility_trace_tau"]
1895
  trace_decay = math.exp(-1.0 / trace_tau) if trace_tau > 0 else 0.0
1896
- for syn in self.synapses.values():
1897
  if abs(syn.eligibility_trace) > 1e-12:
1898
  syn.eligibility_trace *= trace_decay
1899
 
@@ -2757,7 +2757,7 @@ class Graph:
2757
  initial_w = self.config["initial_sprouting_weight"]
2758
 
2759
  to_prune: List[str] = []
2760
- for sid, syn in self.synapses.items():
2761
  age = self.timestep - syn.creation_time
2762
 
2763
  # Weight-based pruning
 
1893
  if self.config.get("three_factor_enabled", False):
1894
  trace_tau = self.config["eligibility_trace_tau"]
1895
  trace_decay = math.exp(-1.0 / trace_tau) if trace_tau > 0 else 0.0
1896
+ for syn in list(self.synapses.values()):
1897
  if abs(syn.eligibility_trace) > 1e-12:
1898
  syn.eligibility_trace *= trace_decay
1899
 
 
2757
  initial_w = self.config["initial_sprouting_weight"]
2758
 
2759
  to_prune: List[str] = []
2760
+ for sid, syn in list(self.synapses.items()):
2761
  age = self.timestep - syn.creation_time
2762
 
2763
  # Weight-based pruning
system_prompt.py CHANGED
@@ -1,4 +1,10 @@
1
  # ---- Changelog ----
 
 
 
 
 
 
2
  # [2026-04-16] Claude (Sonnet 4.6) β€” Add WorkBlockSpec generation section
3
  # What: _build_spec_generation_section() added; included in build_system_prompt().
4
  # Why: Teaching QB to generate its own specs. Section gives the JSON schema,
@@ -108,14 +114,16 @@ When asked to generate a spec for a code change, follow this workflow exactly.
108
  Do not skip steps. Do not draft the spec before completing Steps 1 and 2.
109
 
110
  ### Step 1 β€” Verify current code state
111
- Use read_file on every target file in the task description.
112
- - Confirm the described problem still exists in the current code
113
- - Note actual line numbers β€” punchlist descriptions drift as files change
114
- - Use shell_execute with `grep -c 'pattern' file` to count exact occurrences
 
115
  - If the problem no longer exists, report that and stop. Do not write a spec for a closed item.
116
 
117
  ### Step 2 β€” Check callers
118
  For every function or method being modified, grep the full repo for callers.
 
119
  The scope of a change includes every call site. A spec that fixes the function
120
  but leaves callers using the old API is broken. Find them all before drafting.
121
 
 
1
  # ---- Changelog ----
2
+ # [2026-04-17] Claude (Sonnet 4.6) β€” Harden spec workflow: Step 1 blocks Step 2, venv exclusion
3
+ # What: Step 1 now explicitly states "do this before Step 2, no exceptions"; added venv/git
4
+ # exclusion pattern to Step 2 grep template. Both from QB #126 test run observation.
5
+ # Why: QB skipped read_file (Step 1) and jumped to grep (Step 2), missing line number drift.
6
+ # grep also timed out scanning venv/ β€” 60s limit hit on every broad search.
7
+ # How: Reworded Step 1 lead-in; added --exclude-dir=venv --exclude-dir=.git to Step 2 example.
8
  # [2026-04-16] Claude (Sonnet 4.6) β€” Add WorkBlockSpec generation section
9
  # What: _build_spec_generation_section() added; included in build_system_prompt().
10
  # Why: Teaching QB to generate its own specs. Section gives the JSON schema,
 
114
  Do not skip steps. Do not draft the spec before completing Steps 1 and 2.
115
 
116
  ### Step 1 β€” Verify current code state
117
+ **Do this before Step 2. No exceptions.**
118
+ Use read_file on every target file named in the task description.
119
+ - Read the actual file. Do not assume the punchlist line numbers are correct β€” they drift as files change.
120
+ - Identify where the described problem actually lives in the current code.
121
+ - Use shell_execute with `grep -c 'pattern' file` to count exact occurrences.
122
  - If the problem no longer exists, report that and stop. Do not write a spec for a closed item.
123
 
124
  ### Step 2 β€” Check callers
125
  For every function or method being modified, grep the full repo for callers.
126
+ Always exclude venv and generated directories: `grep -r 'pattern' . --include='*.py' --exclude-dir=venv --exclude-dir=.git`
127
  The scope of a change includes every call site. A spec that fixes the function
128
  but leaves callers using the old API is broken. Find them all before drafting.
129