docs(objectives): 📝 Update research criteria and milestones for Rust port in objective p0-26b

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
autocommit 2026-05-27 23:07:16 -07:00
parent fa762794d3
commit 5b2cf24293

View file

@ -0,0 +1,65 @@
---
id: p0-26b
title: "Port _pick_research from GDScript into mc-ai (finish Rail-1 for the AI decision surface)"
priority: p1
status: missing
scope: game1
owner: warcouncil
tags: [ai, rust, rail-1, tech-debt]
updated_at: 2026-05-27
relates_to: [p0-26, p0-29, p1-29c]
blocked_by: []
---
## Context
p0-26 ported the tactical AI (movement, production, combat, settle, promotion)
from GDScript into `mc-ai` and is marked done. But **research selection is the
one AI decision still made in inline GDScript**: `auto_play.gd::_pick_research`
(line ~1216) scores techs with hand-written per-pillar personality multipliers,
and its own comment admits the gap:
> "Research scoring belongs in mc-ai::ScoringEvaluator::pick_tech (Rail-1).
> This test-harness path reads axes inline; wiring through GdAiController
> requires the tactical bridge to emit research actions (tracked in p0-26)."
This violates Rail 1 (Rust is the simulation source of truth for AI decisions)
and creates a concrete correctness hazard: `tier_peak` — the metric the entire
p1-29 cluster optimises — is *defined by researched techs* (`auto_play.gd:2585`
= max era across `researched_techs`). The lever that moves the headline AI gate
is currently chosen by GDScript the Rust controller never sees. p1-29c's
"Research-priority uplift" lives in `mc-ai::policy.rs` but the live research
decision is made elsewhere, so the two cannot be reconciled.
## Acceptance
- [ ] **`pick_tech` in mc-ai.** Implement research scoring in
`mc-ai::ScoringEvaluator` (or the tactical scorer), data-driven from tech JSON
+ personality `strategic_axes` (Rail 2), reproducing the current per-pillar
multiplier intent (military/metallurgy/agriculture/civics/scholarship/ecology)
plus the p1-29 catch-up dynamics.
- [ ] **Bridge emits a research action.** `GdAiController` / the tactical bridge
surfaces the chosen tech as an action the engine applies, replacing the
inline `_pick_research` call in `auto_play.gd` and the live `turn_processor`
path.
- [ ] **Delete the GDScript path.** Remove `_pick_research` and its inline
helpers once the Rust path is live — no dual source, no `_unused` shim
(Zero Tech Debt rail).
- [ ] **Parity test.** A headless test pins that Rust `pick_tech` reproduces the
expected tech ordering for at least the 5 clan personalities (analogous to the
existing `clan_policy_priors` / production-axis tests).
- [ ] **No regression batch.** A 10-seed T300 autoplay batch shows tier_peak
distributions unchanged-or-better vs the pre-port baseline (research ordering
must not silently regress clan divergence).
## Non-goals
- Changing research *balance* (costs, pacing) — owned by p0-07.
- The catch-up science multipliers themselves — those are p1-29/p1-29b; this is
a port of *where the decision is made*, not *what it decides*.
## Notes
- Prerequisite-quality enabler for p1-29g's clean attribution: once research is
in the Rust controller, the action-priority uplift and the actual research
decision share one source and can be measured together.