fix: bundled dust cleanup — push3-evolution/evolve.sh (#210) (#987)

## Summary

Bundled dust cleanup for `push3-evolution/evolve.sh` subsystem:

- **#716**: Fix null-fitness crash in generation JSONL parsing — `int(d.get('fitness', 0))` → `int(d.get('fitness') or 0)` (avoids `TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'` when fitness is JSON `null`)
- **#944**: Add `processExecIf_fix` to `ZERO_RATED_FLAGS` so inflated scores from that flag are zero-rated during pool admission/eviction
- **#945**: `fitness_flags` is comma-separated in practice — update `manifest.schema.json` description from 'Space-separated' to 'Comma-separated' and use `flags.split(',')` in `effective_fitness` instead of substring match
- Fix pre-existing SC2086: quote `$i` in `printf` argument (ShellCheck)

## Test plan
- [ ] ShellCheck passes on `tools/push3-evolution/evolve.sh`
- [ ] CI passes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: openhands <openhands@all-hands.dev>
Reviewed-on: https://codeberg.org/johba/harb/pulls/987
Reviewed-by: Disinto_bot <disinto_bot@noreply.codeberg.org>
This commit is contained in:
johba 2026-03-19 07:33:23 +01:00
parent e37a93e0e2
commit 052ad7ac1c
2 changed files with 5 additions and 4 deletions

View file

@ -423,7 +423,7 @@ PYEOF
else else
# --- Default mode: N copies of the seed, each independently mutated --- # --- Default mode: N copies of the seed, each independently mutated ---
for i in $(seq 0 $((POPULATION - 1))); do for i in $(seq 0 $((POPULATION - 1))); do
CAND_FILE="$GEN_DIR/candidate_$(printf '%03d' $i).push3" CAND_FILE="$GEN_DIR/candidate_$(printf '%03d' "$i").push3"
MUTATED=$(run_mutate_cli mutate "$SEED" "$MUTATION_RATE") \ MUTATED=$(run_mutate_cli mutate "$SEED" "$MUTATION_RATE") \
|| fail "Failed to mutate seed for initial candidate $i" || fail "Failed to mutate seed for initial candidate $i"
printf '%s\n' "$MUTATED" > "$CAND_FILE" printf '%s\n' "$MUTATED" > "$CAND_FILE"
@ -814,7 +814,7 @@ for fname in sorted(os.listdir(output_dir)):
try: try:
d = json.loads(line) d = json.loads(line)
cid = d.get('candidate_id', '') cid = d.get('candidate_id', '')
fitness = int(d.get('fitness', 0)) fitness = int(d.get('fitness') or 0)
if fitness < threshold: if fitness < threshold:
continue continue
# Canonical CID format is "candidate_XXX" (zero-padded numeric suffix, # Canonical CID format is "candidate_XXX" (zero-padded numeric suffix,
@ -889,11 +889,12 @@ if not new_items:
# Add new inflation/distortion flags here; no other code change is required. # Add new inflation/distortion flags here; no other code change is required.
ZERO_RATED_FLAGS = { ZERO_RATED_FLAGS = {
'token_value_inflation', 'token_value_inflation',
'processExecIf_fix',
} }
def effective_fitness(entry): def effective_fitness(entry):
flags = entry.get('fitness_flags') or '' flags = entry.get('fitness_flags') or ''
if any(flag in flags for flag in ZERO_RATED_FLAGS): if any(flag in flags.split(',') for flag in ZERO_RATED_FLAGS):
return 0 return 0
return int(entry.get('fitness') or 0) return int(entry.get('fitness') or 0)

View file

@ -17,7 +17,7 @@
}, },
"fitness_flags": { "fitness_flags": {
"type": ["string", "null"], "type": ["string", "null"],
"description": "Space-separated flags that qualify or invalidate the fitness value (e.g. token_value_inflation). null when no flags apply." "description": "Comma-separated flags that qualify or invalidate the fitness value (e.g. token_value_inflation). null when no flags apply."
}, },
"origin": { "origin": {
"type": "string", "type": "string",