irregular6612 Claude Opus 4.8 (1M context) commited on
Commit
426093b
ยท
1 Parent(s): 789894f

refactor: restructure proteus into game/web subpackages

Browse files

Move live proteus/ into game/{engine,scenarios,agents,runtime,metrics,viz}
+ web/{local,arena-skeleton} + shared/, providers/ unchanged. Absolute
imports rewritten by tools/restructure_imports.py; five cross-package
relative imports (grid<->engine/scenarios split) and the orphaned engine
README moved by hand. No logic changes; 253 tests green (identical
node-ID set pre/post). pyproject packages=["proteus"] unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

This view is limited to 50 files because it contains too many changes. ย  See raw diff
Files changed (50) hide show
  1. proteus/agents/__init__.py +0 -7
  2. proteus/cli.py +11 -11
  3. proteus/game/__init__.py +7 -0
  4. proteus/game/agents/__init__.py +7 -0
  5. proteus/{agents โ†’ game/agents}/base.py +0 -0
  6. proteus/{agents โ†’ game/agents}/human.py +2 -2
  7. proteus/{agents โ†’ game/agents}/parsing.py +0 -0
  8. proteus/{agents โ†’ game/agents}/vanilla.py +2 -2
  9. proteus/{arc_grid โ†’ game/engine}/README.md +0 -0
  10. proteus/{arc_grid โ†’ game/engine}/__init__.py +0 -0
  11. proteus/{arc_grid โ†’ game/engine}/arcengine/LICENSE +0 -0
  12. proteus/{arc_grid โ†’ game/engine}/arcengine/OVERVIEW.md +0 -0
  13. proteus/{arc_grid โ†’ game/engine}/arcengine/__init__.py +0 -0
  14. proteus/{arc_grid โ†’ game/engine}/arcengine/base_game.py +0 -0
  15. proteus/{arc_grid โ†’ game/engine}/arcengine/camera.py +0 -0
  16. proteus/{arc_grid โ†’ game/engine}/arcengine/enums.py +0 -0
  17. proteus/{arc_grid โ†’ game/engine}/arcengine/interfaces.py +0 -0
  18. proteus/{arc_grid โ†’ game/engine}/arcengine/level.py +0 -0
  19. proteus/{arc_grid โ†’ game/engine}/arcengine/py.typed +0 -0
  20. proteus/{arc_grid โ†’ game/engine}/arcengine/sprites.py +0 -0
  21. proteus/{grid โ†’ game/engine}/ascii_view.py +0 -0
  22. proteus/{grid โ†’ game/engine}/difficulty.py +0 -0
  23. proteus/{grid/game.py โ†’ game/engine/grid.py} +4 -4
  24. proteus/{arc_grid โ†’ game/engine}/rendering.py +0 -0
  25. proteus/game/metrics/__init__.py +7 -0
  26. proteus/{runtime โ†’ game/metrics}/aggregate.py +1 -1
  27. proteus/{runtime โ†’ game/metrics}/metrics.py +1 -1
  28. proteus/{runtime โ†’ game/metrics}/persona.py +0 -0
  29. proteus/{runtime โ†’ game/metrics}/rollout.py +3 -3
  30. proteus/{runtime โ†’ game/runtime}/__init__.py +7 -7
  31. proteus/{runtime โ†’ game/runtime}/_session_core.py +9 -9
  32. proteus/{runtime โ†’ game/runtime}/interactive.py +3 -3
  33. proteus/{runtime โ†’ game/runtime}/io.py +1 -1
  34. proteus/{runtime โ†’ game/runtime}/memory.py +0 -0
  35. proteus/{runtime โ†’ game/runtime}/memory_gen.py +7 -7
  36. proteus/{runtime โ†’ game/runtime}/memory_policies.py +1 -1
  37. proteus/{runtime โ†’ game/runtime}/session.py +7 -7
  38. proteus/{runtime โ†’ game/runtime}/spectate.py +4 -4
  39. proteus/{runtime โ†’ game/runtime}/trace.py +0 -0
  40. proteus/{grid โ†’ game}/scenarios/__init__.py +3 -3
  41. proteus/{grid/scenario.py โ†’ game/scenarios/base.py} +8 -8
  42. proteus/{grid โ†’ game}/scenarios/pack_evade.py +10 -10
  43. proteus/{grid โ†’ game}/scenarios/predator_evade.py +5 -5
  44. proteus/{viz โ†’ game/viz}/__init__.py +5 -5
  45. proteus/{viz โ†’ game/viz}/gif.py +2 -2
  46. proteus/{viz โ†’ game/viz}/png.py +2 -2
  47. proteus/{viz โ†’ game/viz}/reconstruct.py +5 -5
  48. proteus/{viz โ†’ game/viz}/terminal.py +2 -2
  49. proteus/grid/__init__.py +0 -10
  50. proteus/shared/__init__.py +6 -0
proteus/agents/__init__.py DELETED
@@ -1,7 +0,0 @@
1
- """proteus.agents โ€” slim LLM agent abstraction (no forfeit/stake/risk)."""
2
-
3
- from proteus.agents.base import Agent, ActResult, ProbeResult
4
- from proteus.agents.human import HumanAgent
5
- from proteus.agents.vanilla import VanillaAgent
6
-
7
- __all__ = ["Agent", "ActResult", "ProbeResult", "HumanAgent", "VanillaAgent"]
 
 
 
 
 
 
 
 
proteus/cli.py CHANGED
@@ -15,19 +15,19 @@ from __future__ import annotations
15
  import argparse
16
  import sys
17
 
18
- import proteus.grid # noqa: F401 โ€” side-effect: populate the scenario registry
19
- from proteus.agents import HumanAgent, VanillaAgent
20
- from proteus.grid.difficulty import Difficulty
21
- from proteus.grid.scenario import list_scenarios
22
  from proteus.providers import available_providers, make_provider
23
- from proteus.runtime import SessionRunner, append_trace, read_traces
24
- from proteus.runtime.memory import (
25
  latest_for_model,
26
  load_checkpoint,
27
  save_checkpoint,
28
  )
29
- from proteus.runtime.memory_gen import generate_memory
30
- from proteus.runtime.persona import available_personas, get_persona
31
 
32
 
33
  def _cmd_run(args: argparse.Namespace) -> int:
@@ -100,7 +100,7 @@ def _auto_gif(out_path: str | None, no_gif: bool) -> None:
100
  return
101
  from pathlib import Path
102
 
103
- from proteus.viz import reconstruct, write_gif
104
 
105
  gif_path = Path(out_path).with_suffix(".gif")
106
  for trace in read_traces(out_path):
@@ -233,7 +233,7 @@ def _cmd_replay(args: argparse.Namespace) -> int:
233
  return 1
234
 
235
  if args.visual or args.png:
236
- from proteus.viz import reconstruct, render_terminal, write_pngs
237
 
238
  for trace in traces:
239
  steps = reconstruct(trace)
@@ -264,7 +264,7 @@ def _cmd_replay(args: argparse.Namespace) -> int:
264
  def _cmd_compare(args: argparse.Namespace) -> int:
265
  import json
266
 
267
- from proteus.runtime.aggregate import aggregate_traces
268
 
269
  all_traces = []
270
  for path in args.trace_files:
 
15
  import argparse
16
  import sys
17
 
18
+ import proteus.game.scenarios # noqa: F401 โ€” side-effect: populate the scenario registry
19
+ from proteus.game.agents import HumanAgent, VanillaAgent
20
+ from proteus.game.engine.difficulty import Difficulty
21
+ from proteus.game.scenarios.base import list_scenarios
22
  from proteus.providers import available_providers, make_provider
23
+ from proteus.game.runtime import SessionRunner, append_trace, read_traces
24
+ from proteus.game.runtime.memory import (
25
  latest_for_model,
26
  load_checkpoint,
27
  save_checkpoint,
28
  )
29
+ from proteus.game.runtime.memory_gen import generate_memory
30
+ from proteus.game.metrics.persona import available_personas, get_persona
31
 
32
 
33
  def _cmd_run(args: argparse.Namespace) -> int:
 
100
  return
101
  from pathlib import Path
102
 
103
+ from proteus.game.viz import reconstruct, write_gif
104
 
105
  gif_path = Path(out_path).with_suffix(".gif")
106
  for trace in read_traces(out_path):
 
233
  return 1
234
 
235
  if args.visual or args.png:
236
+ from proteus.game.viz import reconstruct, render_terminal, write_pngs
237
 
238
  for trace in traces:
239
  steps = reconstruct(trace)
 
264
  def _cmd_compare(args: argparse.Namespace) -> int:
265
  import json
266
 
267
+ from proteus.game.metrics.aggregate import aggregate_traces
268
 
269
  all_traces = []
270
  for path in args.trace_files:
proteus/game/__init__.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ """proteus.game โ€” the grid game and evaluation engine.
2
+
3
+ Subpackages: engine (world/physics + vendored ARC engine), scenarios
4
+ (Scenario ABC + registry + concrete scenarios), agents (player interface),
5
+ runtime (session orchestration, trace, memory, I/O), metrics (scoring),
6
+ viz (trace visualization). game never imports proteus.web.
7
+ """
proteus/game/agents/__init__.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ """proteus.game.agents โ€” slim LLM agent abstraction (no forfeit/stake/risk)."""
2
+
3
+ from proteus.game.agents.base import Agent, ActResult, ProbeResult
4
+ from proteus.game.agents.human import HumanAgent
5
+ from proteus.game.agents.vanilla import VanillaAgent
6
+
7
+ __all__ = ["Agent", "ActResult", "ProbeResult", "HumanAgent", "VanillaAgent"]
proteus/{agents โ†’ game/agents}/base.py RENAMED
File without changes
proteus/{agents โ†’ game/agents}/human.py RENAMED
@@ -7,7 +7,7 @@ SessionTrace schema-identical to an LLM trace, so the two compare directly
7
  input stream โ€” no TTY, no network.
8
 
9
  Fairness note: the live view is the ASCII observation the LLM also sees; the
10
- truecolor / PNG renderers are reserved for post-hoc replay (proteus.viz), so a
11
  human baseline reads exactly what the model reads.
12
  """
13
 
@@ -16,7 +16,7 @@ from __future__ import annotations
16
  import builtins
17
  from typing import Callable, Optional
18
 
19
- from proteus.agents.base import Agent, ActResult, ProbeResult
20
 
21
  # Single-key shortcuts -> canonical action strings (WASD).
22
  _SHORTCUTS = {"w": "up", "a": "left", "s": "down", "d": "right"}
 
7
  input stream โ€” no TTY, no network.
8
 
9
  Fairness note: the live view is the ASCII observation the LLM also sees; the
10
+ truecolor / PNG renderers are reserved for post-hoc replay (proteus.game.viz), so a
11
  human baseline reads exactly what the model reads.
12
  """
13
 
 
16
  import builtins
17
  from typing import Callable, Optional
18
 
19
+ from proteus.game.agents.base import Agent, ActResult, ProbeResult
20
 
21
  # Single-key shortcuts -> canonical action strings (WASD).
22
  _SHORTCUTS = {"w": "up", "a": "left", "s": "down", "d": "right"}
proteus/{agents โ†’ game/agents}/parsing.py RENAMED
File without changes
proteus/{agents โ†’ game/agents}/vanilla.py RENAMED
@@ -8,8 +8,8 @@ as the agent's reasoning even when the action text is terse.
8
 
9
  from __future__ import annotations
10
 
11
- from proteus.agents.base import Agent, ActResult, ProbeResult
12
- from proteus.agents.parsing import extract_action
13
  from proteus.providers.base import LLMProvider
14
  from proteus.providers.thinking_utils import parse_thinking_tags
15
 
 
8
 
9
  from __future__ import annotations
10
 
11
+ from proteus.game.agents.base import Agent, ActResult, ProbeResult
12
+ from proteus.game.agents.parsing import extract_action
13
  from proteus.providers.base import LLMProvider
14
  from proteus.providers.thinking_utils import parse_thinking_tags
15
 
proteus/{arc_grid โ†’ game/engine}/README.md RENAMED
File without changes
proteus/{arc_grid โ†’ game/engine}/__init__.py RENAMED
File without changes
proteus/{arc_grid โ†’ game/engine}/arcengine/LICENSE RENAMED
File without changes
proteus/{arc_grid โ†’ game/engine}/arcengine/OVERVIEW.md RENAMED
File without changes
proteus/{arc_grid โ†’ game/engine}/arcengine/__init__.py RENAMED
File without changes
proteus/{arc_grid โ†’ game/engine}/arcengine/base_game.py RENAMED
File without changes
proteus/{arc_grid โ†’ game/engine}/arcengine/camera.py RENAMED
File without changes
proteus/{arc_grid โ†’ game/engine}/arcengine/enums.py RENAMED
File without changes
proteus/{arc_grid โ†’ game/engine}/arcengine/interfaces.py RENAMED
File without changes
proteus/{arc_grid โ†’ game/engine}/arcengine/level.py RENAMED
File without changes
proteus/{arc_grid โ†’ game/engine}/arcengine/py.typed RENAMED
File without changes
proteus/{arc_grid โ†’ game/engine}/arcengine/sprites.py RENAMED
File without changes
proteus/{grid โ†’ game/engine}/ascii_view.py RENAMED
File without changes
proteus/{grid โ†’ game/engine}/difficulty.py RENAMED
File without changes
proteus/{grid/game.py โ†’ game/engine/grid.py} RENAMED
@@ -1,6 +1,6 @@
1
  """MotiveGridGame โ€” the shared per-turn game loop for the motive_grid family.
2
 
3
- ``MotiveGridGame`` subclasses ``proteus.arc_grid.ARCBaseGame``. It owns the
4
  turn loop and delegates all scenario-specific behaviour (level construction,
5
  threat motion, elimination, answer keys) to an injected :class:`Scenario`.
6
 
@@ -20,7 +20,7 @@ from typing import TYPE_CHECKING
20
 
21
  import numpy as np
22
 
23
- from proteus.arc_grid import (
24
  ARCBaseGame,
25
  ActionInput,
26
  Camera,
@@ -30,7 +30,7 @@ from proteus.arc_grid import (
30
  )
31
 
32
  if TYPE_CHECKING:
33
- from .scenario import Scenario
34
 
35
  # Action string -> (dx, dy) grid delta. y grows downward (arc_grid convention).
36
  _DIRECTION_DELTAS: dict[str, tuple[int, int]] = {
@@ -217,7 +217,7 @@ class MotiveGridGame(ARCBaseGame):
217
  name: The sprite name to look up on the current level.
218
 
219
  Returns:
220
- The matching :class:`~proteus.arc_grid.Sprite`, or ``None``.
221
  """
222
  sprites = self.current_level.get_sprites_by_name(name)
223
  return sprites[0] if sprites else None
 
1
  """MotiveGridGame โ€” the shared per-turn game loop for the motive_grid family.
2
 
3
+ ``MotiveGridGame`` subclasses ``proteus.game.engine.ARCBaseGame``. It owns the
4
  turn loop and delegates all scenario-specific behaviour (level construction,
5
  threat motion, elimination, answer keys) to an injected :class:`Scenario`.
6
 
 
20
 
21
  import numpy as np
22
 
23
+ from proteus.game.engine import (
24
  ARCBaseGame,
25
  ActionInput,
26
  Camera,
 
30
  )
31
 
32
  if TYPE_CHECKING:
33
+ from ..scenarios.base import Scenario
34
 
35
  # Action string -> (dx, dy) grid delta. y grows downward (arc_grid convention).
36
  _DIRECTION_DELTAS: dict[str, tuple[int, int]] = {
 
217
  name: The sprite name to look up on the current level.
218
 
219
  Returns:
220
+ The matching :class:`~proteus.game.engine.Sprite`, or ``None``.
221
  """
222
  sprites = self.current_level.get_sprites_by_name(name)
223
  return sprites[0] if sprites else None
proteus/{arc_grid โ†’ game/engine}/rendering.py RENAMED
File without changes
proteus/game/metrics/__init__.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ """proteus.game.metrics โ€” scoring and evaluation.
2
+
3
+ Submodules: metrics (compute_metrics), persona (PersonaWeights, reference
4
+ policies), rollout (optimal_rollout), aggregate (aggregate_traces). Import the
5
+ submodules directly (e.g. proteus.game.metrics.persona) to avoid an __init__
6
+ import cycle with proteus.game.runtime.trace.
7
+ """
proteus/{runtime โ†’ game/metrics}/aggregate.py RENAMED
@@ -6,7 +6,7 @@ Pure functions only (no I/O), so the aggregation is headless-testable. The CLI
6
 
7
  from __future__ import annotations
8
 
9
- from proteus.runtime.trace import SessionTrace
10
 
11
 
12
  def aggregate_traces(
 
6
 
7
  from __future__ import annotations
8
 
9
+ from proteus.game.runtime.trace import SessionTrace
10
 
11
 
12
  def aggregate_traces(
proteus/{runtime โ†’ game/metrics}/metrics.py RENAMED
@@ -34,7 +34,7 @@ the pre-predator position) without redefinition.
34
 
35
  from __future__ import annotations
36
 
37
- from proteus.runtime.trace import TurnTrace
38
 
39
 
40
  def compute_metrics(
 
34
 
35
  from __future__ import annotations
36
 
37
+ from proteus.game.runtime.trace import TurnTrace
38
 
39
 
40
  def compute_metrics(
proteus/{runtime โ†’ game/metrics}/persona.py RENAMED
File without changes
proteus/{runtime โ†’ game/metrics}/rollout.py RENAMED
@@ -12,9 +12,9 @@ from __future__ import annotations
12
  import random
13
  from dataclasses import dataclass
14
 
15
- from proteus.grid.difficulty import Difficulty
16
- from proteus.grid.game import MotiveGridGame
17
- from proteus.grid.scenario import get_scenario
18
 
19
 
20
  @dataclass(frozen=True)
 
12
  import random
13
  from dataclasses import dataclass
14
 
15
+ from proteus.game.engine.difficulty import Difficulty
16
+ from proteus.game.engine.grid import MotiveGridGame
17
+ from proteus.game.scenarios.base import get_scenario
18
 
19
 
20
  @dataclass(frozen=True)
proteus/{runtime โ†’ game/runtime}/__init__.py RENAMED
@@ -1,10 +1,10 @@
1
- """proteus.runtime โ€” session orchestration, trace, metrics, and I/O."""
2
 
3
- from proteus.runtime.session import SessionRunner
4
- from proteus.runtime.trace import SessionTrace, TurnTrace
5
- from proteus.runtime.metrics import compute_metrics
6
- from proteus.runtime.io import append_trace, read_traces
7
- from proteus.runtime.memory import (
8
  MemoryCheckpoint,
9
  MemoryTurn,
10
  save_checkpoint,
@@ -12,7 +12,7 @@ from proteus.runtime.memory import (
12
  latest_for_model,
13
  render_memory_block,
14
  )
15
- from proteus.runtime.memory_gen import generate_memory
16
 
17
  __all__ = [
18
  "SessionRunner",
 
1
+ """proteus.game.runtime โ€” session orchestration, trace, metrics, and I/O."""
2
 
3
+ from proteus.game.runtime.session import SessionRunner
4
+ from proteus.game.runtime.trace import SessionTrace, TurnTrace
5
+ from proteus.game.metrics.metrics import compute_metrics
6
+ from proteus.game.runtime.io import append_trace, read_traces
7
+ from proteus.game.runtime.memory import (
8
  MemoryCheckpoint,
9
  MemoryTurn,
10
  save_checkpoint,
 
12
  latest_for_model,
13
  render_memory_block,
14
  )
15
+ from proteus.game.runtime.memory_gen import generate_memory
16
 
17
  __all__ = [
18
  "SessionRunner",
proteus/{runtime โ†’ game/runtime}/_session_core.py RENAMED
@@ -16,20 +16,20 @@ from dataclasses import dataclass
16
 
17
  import numpy as np
18
 
19
- from proteus.grid.ascii_view import frame_to_ascii, legend_text
20
- from proteus.grid.difficulty import Difficulty
21
- from proteus.grid.game import MotiveGridGame
22
- from proteus.grid.scenario import Scenario, get_scenario
23
- from proteus.runtime.memory import MemoryCheckpoint, render_memory_block
24
- from proteus.runtime.metrics import compute_metrics
25
- from proteus.runtime.persona import (
26
  PersonaWeights,
27
  pressure as persona_pressure,
28
  reference_actions,
29
  reward_rw,
30
  )
31
- from proteus.runtime.rollout import optimal_rollout
32
- from proteus.runtime.trace import SessionTrace, TurnTrace
33
 
34
  _ACTIONS = ["up", "down", "left", "right", "stay"]
35
  _DIRECTIONS = {"up", "down", "left", "right"}
 
16
 
17
  import numpy as np
18
 
19
+ from proteus.game.engine.ascii_view import frame_to_ascii, legend_text
20
+ from proteus.game.engine.difficulty import Difficulty
21
+ from proteus.game.engine.grid import MotiveGridGame
22
+ from proteus.game.scenarios.base import Scenario, get_scenario
23
+ from proteus.game.runtime.memory import MemoryCheckpoint, render_memory_block
24
+ from proteus.game.metrics.metrics import compute_metrics
25
+ from proteus.game.metrics.persona import (
26
  PersonaWeights,
27
  pressure as persona_pressure,
28
  reference_actions,
29
  reward_rw,
30
  )
31
+ from proteus.game.metrics.rollout import optimal_rollout
32
+ from proteus.game.runtime.trace import SessionTrace, TurnTrace
33
 
34
  _ACTIONS = ["up", "down", "left", "right", "stay"]
35
  _DIRECTIONS = {"up", "down", "left", "right"}
proteus/{runtime โ†’ game/runtime}/interactive.py RENAMED
@@ -11,9 +11,9 @@ only once the game is over.
11
  """
12
  from __future__ import annotations
13
 
14
- from proteus.grid.difficulty import Difficulty
15
- from proteus.runtime import _session_core as core
16
- from proteus.runtime.trace import SessionTrace, TurnTrace
17
 
18
 
19
  class InteractiveSession:
 
11
  """
12
  from __future__ import annotations
13
 
14
+ from proteus.game.engine.difficulty import Difficulty
15
+ from proteus.game.runtime import _session_core as core
16
+ from proteus.game.runtime.trace import SessionTrace, TurnTrace
17
 
18
 
19
  class InteractiveSession:
proteus/{runtime โ†’ game/runtime}/io.py RENAMED
@@ -10,7 +10,7 @@ from __future__ import annotations
10
 
11
  from pathlib import Path
12
 
13
- from proteus.runtime.trace import SessionTrace
14
 
15
 
16
  def append_trace(trace: SessionTrace, path: str | Path) -> Path:
 
10
 
11
  from pathlib import Path
12
 
13
+ from proteus.game.runtime.trace import SessionTrace
14
 
15
 
16
  def append_trace(trace: SessionTrace, path: str | Path) -> Path:
proteus/{runtime โ†’ game/runtime}/memory.py RENAMED
File without changes
proteus/{runtime โ†’ game/runtime}/memory_gen.py RENAMED
@@ -12,13 +12,13 @@ import random
12
  from datetime import datetime, timezone
13
  from typing import Callable
14
 
15
- from proteus.agents.base import Agent
16
- from proteus.grid.ascii_view import legend_text
17
- from proteus.grid.difficulty import Difficulty
18
- from proteus.grid.game import MotiveGridGame
19
- from proteus.grid.scenario import get_scenario
20
- from proteus.runtime.memory import MemoryCheckpoint, MemoryTurn
21
- from proteus.runtime.persona import PersonaWeights, reference_actions
22
 
23
  _ACTIONS = ["up", "down", "left", "right", "stay"]
24
  _REASONING_LIMIT = 2000 # cap stored reasoning so checkpoints stay small
 
12
  from datetime import datetime, timezone
13
  from typing import Callable
14
 
15
+ from proteus.game.agents.base import Agent
16
+ from proteus.game.engine.ascii_view import legend_text
17
+ from proteus.game.engine.difficulty import Difficulty
18
+ from proteus.game.engine.grid import MotiveGridGame
19
+ from proteus.game.scenarios.base import get_scenario
20
+ from proteus.game.runtime.memory import MemoryCheckpoint, MemoryTurn
21
+ from proteus.game.metrics.persona import PersonaWeights, reference_actions
22
 
23
  _ACTIONS = ["up", "down", "left", "right", "stay"]
24
  _REASONING_LIMIT = 2000 # cap stored reasoning so checkpoints stay small
proteus/{runtime โ†’ game/runtime}/memory_policies.py RENAMED
@@ -1,7 +1,7 @@
1
  """Scripted hand-authored memory policies for pack_evade demonstrations.
2
 
3
  Each policy is a deterministic ``policy(scenario, game) -> action`` callable used
4
- by :func:`proteus.runtime.memory_gen.generate_memory` (the ``policy=`` path) to
5
  produce a 100-turn handover-memory trajectory with a distinct *motive*:
6
 
7
  - ``survival_dynamic`` โ€” keep maximum distance from the predator (evade, moving).
 
1
  """Scripted hand-authored memory policies for pack_evade demonstrations.
2
 
3
  Each policy is a deterministic ``policy(scenario, game) -> action`` callable used
4
+ by :func:`proteus.game.runtime.memory_gen.generate_memory` (the ``policy=`` path) to
5
  produce a 100-turn handover-memory trajectory with a distinct *motive*:
6
 
7
  - ``survival_dynamic`` โ€” keep maximum distance from the predator (evade, moving).
proteus/{runtime โ†’ game/runtime}/session.py RENAMED
@@ -4,18 +4,18 @@ One session: build the scenario+game from (scenario, seed, difficulty), replay
4
  the scripted Cut pre-roll, hand control to the agent for up to ``play_turns``
5
  turns (observation -> optional probe -> act -> apply -> record), and emit a
6
  scored SessionTrace. The per-session mechanics are shared with InteractiveSession
7
- via ``proteus.runtime._session_core`` (single source of truth) โ€” including the
8
  CP7 memory pre-roll (prepended to the turn-1 observation) and the CP8 persona
9
  reference/regret bookkeeping, both threaded through the shared helpers.
10
  """
11
  from __future__ import annotations
12
 
13
- from proteus.agents.base import Agent
14
- from proteus.grid.difficulty import Difficulty
15
- from proteus.runtime import _session_core as core
16
- from proteus.runtime.memory import MemoryCheckpoint
17
- from proteus.runtime.persona import PersonaWeights
18
- from proteus.runtime.trace import SessionTrace, TurnTrace
19
 
20
 
21
  class SessionRunner:
 
4
  the scripted Cut pre-roll, hand control to the agent for up to ``play_turns``
5
  turns (observation -> optional probe -> act -> apply -> record), and emit a
6
  scored SessionTrace. The per-session mechanics are shared with InteractiveSession
7
+ via ``proteus.game.runtime._session_core`` (single source of truth) โ€” including the
8
  CP7 memory pre-roll (prepended to the turn-1 observation) and the CP8 persona
9
  reference/regret bookkeeping, both threaded through the shared helpers.
10
  """
11
  from __future__ import annotations
12
 
13
+ from proteus.game.agents.base import Agent
14
+ from proteus.game.engine.difficulty import Difficulty
15
+ from proteus.game.runtime import _session_core as core
16
+ from proteus.game.runtime.memory import MemoryCheckpoint
17
+ from proteus.game.metrics.persona import PersonaWeights
18
+ from proteus.game.runtime.trace import SessionTrace, TurnTrace
19
 
20
 
21
  class SessionRunner:
proteus/{runtime โ†’ game/runtime}/spectate.py RENAMED
@@ -11,10 +11,10 @@ model itself still only ever receives the observation passed to ``agent.act``.)
11
  """
12
  from __future__ import annotations
13
 
14
- from proteus.agents.base import Agent
15
- from proteus.grid.difficulty import Difficulty
16
- from proteus.runtime import _session_core as core
17
- from proteus.runtime.trace import SessionTrace, TurnTrace
18
 
19
 
20
  class SpectateSession:
 
11
  """
12
  from __future__ import annotations
13
 
14
+ from proteus.game.agents.base import Agent
15
+ from proteus.game.engine.difficulty import Difficulty
16
+ from proteus.game.runtime import _session_core as core
17
+ from proteus.game.runtime.trace import SessionTrace, TurnTrace
18
 
19
 
20
  class SpectateSession:
proteus/{runtime โ†’ game/runtime}/trace.py RENAMED
File without changes
proteus/{grid โ†’ game}/scenarios/__init__.py RENAMED
@@ -1,10 +1,10 @@
1
  """Scenario implementations for the motive_grid family.
2
 
3
  Importing this package fires each scenario's ``@register_scenario`` decorator,
4
- populating the registry in :mod:`proteus.grid.scenario`.
5
  """
6
 
7
- from proteus.grid.scenarios import predator_evade # noqa: F401 โ€” side-effect: register
8
- from proteus.grid.scenarios import pack_evade # noqa: F401 โ€” side-effect: register
9
 
10
  __all__ = ["predator_evade", "pack_evade"]
 
1
  """Scenario implementations for the motive_grid family.
2
 
3
  Importing this package fires each scenario's ``@register_scenario`` decorator,
4
+ populating the registry in :mod:`proteus.game.scenarios.base`.
5
  """
6
 
7
+ from proteus.game.scenarios import predator_evade # noqa: F401 โ€” side-effect: register
8
+ from proteus.game.scenarios import pack_evade # noqa: F401 โ€” side-effect: register
9
 
10
  __all__ = ["predator_evade", "pack_evade"]
proteus/{grid/scenario.py โ†’ game/scenarios/base.py} RENAMED
@@ -7,9 +7,9 @@ and the prediction/discrimination answer keys) while the shared turn loop in
7
 
8
  Concrete scenarios register themselves via the ``@register_scenario``
9
  decorator, mirroring the task-module registry at
10
- ``proteus.grid``::
11
 
12
- from proteus.grid.scenario import (
13
  Scenario, register_scenario,
14
  )
15
 
@@ -18,7 +18,7 @@ decorator, mirroring the task-module registry at
18
  ...
19
 
20
  # Elsewhere:
21
- from proteus.grid.scenario import get_scenario
22
  scenario = get_scenario("predator_evade")()
23
 
24
  See ``docs/superpowers/specs/2026-06-01-motive-grid-design.md`` ยง4 for the
@@ -31,15 +31,15 @@ import random
31
  from abc import ABC, abstractmethod
32
  from typing import TYPE_CHECKING
33
 
34
- from proteus.arc_grid import Level
35
 
36
  if TYPE_CHECKING:
37
  # Imported only for type checking to avoid a runtime circular import:
38
  # game.py imports scenario.py is NOT done at runtime; instead a Scenario
39
  # is injected into MotiveGridGame, and the game reads it back here only
40
  # for annotations.
41
- from .game import MotiveGridGame
42
- from .difficulty import Difficulty
43
 
44
 
45
  class Scenario(ABC):
@@ -79,7 +79,7 @@ class Scenario(ABC):
79
  difficulty: The session difficulty band (a ``Difficulty``).
80
 
81
  Returns:
82
- A freshly built :class:`~proteus.arc_grid.Level`.
83
  """
84
  raise NotImplementedError
85
 
@@ -216,7 +216,7 @@ class Scenario(ABC):
216
  scenarios override this with a compact textual state so the observation
217
  is not a several-thousand-character grid.
218
  """
219
- from proteus.grid.ascii_view import frame_to_ascii
220
  return frame_to_ascii(game.current_grid(), self.legend())
221
 
222
  def default_memory(self, seed, difficulty):
 
7
 
8
  Concrete scenarios register themselves via the ``@register_scenario``
9
  decorator, mirroring the task-module registry at
10
+ ``proteus.game.scenarios``::
11
 
12
+ from proteus.game.scenarios.base import (
13
  Scenario, register_scenario,
14
  )
15
 
 
18
  ...
19
 
20
  # Elsewhere:
21
+ from proteus.game.scenarios.base import get_scenario
22
  scenario = get_scenario("predator_evade")()
23
 
24
  See ``docs/superpowers/specs/2026-06-01-motive-grid-design.md`` ยง4 for the
 
31
  from abc import ABC, abstractmethod
32
  from typing import TYPE_CHECKING
33
 
34
+ from proteus.game.engine import Level
35
 
36
  if TYPE_CHECKING:
37
  # Imported only for type checking to avoid a runtime circular import:
38
  # game.py imports scenario.py is NOT done at runtime; instead a Scenario
39
  # is injected into MotiveGridGame, and the game reads it back here only
40
  # for annotations.
41
+ from ..engine.grid import MotiveGridGame
42
+ from ..engine.difficulty import Difficulty
43
 
44
 
45
  class Scenario(ABC):
 
79
  difficulty: The session difficulty band (a ``Difficulty``).
80
 
81
  Returns:
82
+ A freshly built :class:`~proteus.game.engine.Level`.
83
  """
84
  raise NotImplementedError
85
 
 
216
  scenarios override this with a compact textual state so the observation
217
  is not a several-thousand-character grid.
218
  """
219
+ from proteus.game.engine.ascii_view import frame_to_ascii
220
  return frame_to_ascii(game.current_grid(), self.legend())
221
 
222
  def default_memory(self, seed, difficulty):
proteus/{grid โ†’ game}/scenarios/pack_evade.py RENAMED
@@ -2,7 +2,7 @@
2
 
3
  A single 5x5 predator hunts a 3x3 focal agent (the lone survivor of a pack of
4
  three; the two that were caught live only in the hand-authored handover memory,
5
- see ``proteus.runtime.pack_evade_memory``). The field is open (no walls), so all
6
  geometry is **center-to-center Manhattan** โ€” no BFS. There is no habit/diagnostic
7
  (``optimal_action == habit_action`` always): this is pure evasion.
8
 
@@ -15,14 +15,14 @@ from __future__ import annotations
15
  import random
16
  from typing import TYPE_CHECKING
17
 
18
- from proteus.arc_grid import BlockingMode, Level, Sprite
19
- from proteus.grid.difficulty import Difficulty
20
 
21
- from ..scenario import Scenario, register_scenario
22
 
23
  if TYPE_CHECKING:
24
- from ..game import MotiveGridGame
25
- from proteus.runtime.memory import MemoryCheckpoint
26
 
27
  BACKGROUND_IDX = 5 # arc_grid Camera default background
28
  FOCAL_IDX = 1
@@ -441,7 +441,7 @@ class PackEvade(Scenario):
441
  """True iff the 3x3 focal footprint anchored at *cell* is on-grid + wall-free.
442
 
443
  Used only by the shared hidden-persona reference policy
444
- (``proteus.runtime.persona``), which calls it on the focal's top-left
445
  anchor, so footprint-awareness is exactly the right semantics here.
446
  """
447
  return self._footprint_free(game, game.focal_sprite, cell[0], cell[1])
@@ -473,10 +473,10 @@ class PackEvade(Scenario):
473
  actually plays a pack_evade episode, and that self-play trajectory is the
474
  handover memory. The eval model sees only the behaviour (the raw weights
475
  are never serialized) and must infer/maintain the persona. Reuses the
476
- CP7/CP8 generator (``proteus.runtime.memory_gen``) in its persona mode.
477
  """
478
- from proteus.runtime.memory_gen import generate_memory
479
- from proteus.runtime.persona import get_persona
480
 
481
  return generate_memory(
482
  "pack_evade", None,
 
2
 
3
  A single 5x5 predator hunts a 3x3 focal agent (the lone survivor of a pack of
4
  three; the two that were caught live only in the hand-authored handover memory,
5
+ see ``proteus.game.runtime.pack_evade_memory``). The field is open (no walls), so all
6
  geometry is **center-to-center Manhattan** โ€” no BFS. There is no habit/diagnostic
7
  (``optimal_action == habit_action`` always): this is pure evasion.
8
 
 
15
  import random
16
  from typing import TYPE_CHECKING
17
 
18
+ from proteus.game.engine import BlockingMode, Level, Sprite
19
+ from proteus.game.engine.difficulty import Difficulty
20
 
21
+ from .base import Scenario, register_scenario
22
 
23
  if TYPE_CHECKING:
24
+ from ..engine.grid import MotiveGridGame
25
+ from proteus.game.runtime.memory import MemoryCheckpoint
26
 
27
  BACKGROUND_IDX = 5 # arc_grid Camera default background
28
  FOCAL_IDX = 1
 
441
  """True iff the 3x3 focal footprint anchored at *cell* is on-grid + wall-free.
442
 
443
  Used only by the shared hidden-persona reference policy
444
+ (``proteus.game.metrics.persona``), which calls it on the focal's top-left
445
  anchor, so footprint-awareness is exactly the right semantics here.
446
  """
447
  return self._footprint_free(game, game.focal_sprite, cell[0], cell[1])
 
473
  actually plays a pack_evade episode, and that self-play trajectory is the
474
  handover memory. The eval model sees only the behaviour (the raw weights
475
  are never serialized) and must infer/maintain the persona. Reuses the
476
+ CP7/CP8 generator (``proteus.game.runtime.memory_gen``) in its persona mode.
477
  """
478
+ from proteus.game.runtime.memory_gen import generate_memory
479
+ from proteus.game.metrics.persona import get_persona
480
 
481
  return generate_memory(
482
  "pack_evade", None,
proteus/{grid โ†’ game}/scenarios/predator_evade.py RENAMED
@@ -63,13 +63,13 @@ from collections import deque
63
  from dataclasses import dataclass
64
  from typing import TYPE_CHECKING
65
 
66
- from proteus.arc_grid import BlockingMode, Level, Sprite
67
- from proteus.grid.difficulty import Difficulty
68
 
69
- from ..scenario import Scenario, register_scenario
70
 
71
  if TYPE_CHECKING:
72
- from ..game import MotiveGridGame
73
 
74
  # --------------------------------------------------------------------------- #
75
  # Palette indices (must match build_level pixels and legend()).
@@ -238,7 +238,7 @@ class PredatorEvade(Scenario):
238
  difficulty: The session difficulty band.
239
 
240
  Returns:
241
- A :class:`~proteus.arc_grid.Level` with focal, predator, and walls.
242
  """
243
  del rng # deterministic hand-authored layouts
244
  layout = _LAYOUTS.get(difficulty, _LAYOUTS[Difficulty.EASY])
 
63
  from dataclasses import dataclass
64
  from typing import TYPE_CHECKING
65
 
66
+ from proteus.game.engine import BlockingMode, Level, Sprite
67
+ from proteus.game.engine.difficulty import Difficulty
68
 
69
+ from .base import Scenario, register_scenario
70
 
71
  if TYPE_CHECKING:
72
+ from ..engine.grid import MotiveGridGame
73
 
74
  # --------------------------------------------------------------------------- #
75
  # Palette indices (must match build_level pixels and legend()).
 
238
  difficulty: The session difficulty band.
239
 
240
  Returns:
241
+ A :class:`~proteus.game.engine.Level` with focal, predator, and walls.
242
  """
243
  del rng # deterministic hand-authored layouts
244
  layout = _LAYOUTS.get(difficulty, _LAYOUTS[Difficulty.EASY])
proteus/{viz โ†’ game/viz}/__init__.py RENAMED
@@ -1,4 +1,4 @@
1
- """proteus.viz โ€” human/debug visualization of a SessionTrace.
2
 
3
  Frames are reconstructed by deterministically replaying the trace through the
4
  real engine (reconstruct), then rendered to the terminal (truecolor + side
@@ -6,15 +6,15 @@ panel) or to per-frame PNGs. matplotlib (the `viz` extra) is imported lazily by
6
  the PNG writer only, so importing this package stays offline-safe.
7
  """
8
 
9
- from proteus.viz.gif import write_gif
10
- from proteus.viz.png import write_pngs
11
- from proteus.viz.reconstruct import (
12
  FrameMeta,
13
  FrameStep,
14
  TraceReconstructionError,
15
  reconstruct,
16
  )
17
- from proteus.viz.terminal import render as render_terminal
18
 
19
  __all__ = [
20
  "FrameMeta",
 
1
+ """proteus.game.viz โ€” human/debug visualization of a SessionTrace.
2
 
3
  Frames are reconstructed by deterministically replaying the trace through the
4
  real engine (reconstruct), then rendered to the terminal (truecolor + side
 
6
  the PNG writer only, so importing this package stays offline-safe.
7
  """
8
 
9
+ from proteus.game.viz.gif import write_gif
10
+ from proteus.game.viz.png import write_pngs
11
+ from proteus.game.viz.reconstruct import (
12
  FrameMeta,
13
  FrameStep,
14
  TraceReconstructionError,
15
  reconstruct,
16
  )
17
+ from proteus.game.viz.terminal import render as render_terminal
18
 
19
  __all__ = [
20
  "FrameMeta",
proteus/{viz โ†’ game/viz}/gif.py RENAMED
@@ -10,8 +10,8 @@ from __future__ import annotations
10
  from pathlib import Path
11
  from typing import Union
12
 
13
- from proteus.arc_grid.rendering import COLOR_MAP, frame_to_rgb_array
14
- from proteus.viz.reconstruct import FrameStep
15
 
16
 
17
  def write_gif(
 
10
  from pathlib import Path
11
  from typing import Union
12
 
13
+ from proteus.game.engine.rendering import COLOR_MAP, frame_to_rgb_array
14
+ from proteus.game.viz.reconstruct import FrameStep
15
 
16
 
17
  def write_gif(
proteus/{viz โ†’ game/viz}/png.py RENAMED
@@ -12,8 +12,8 @@ from __future__ import annotations
12
  from pathlib import Path
13
  from typing import Union
14
 
15
- from proteus.arc_grid.rendering import COLOR_MAP, frame_to_rgb_array
16
- from proteus.viz.reconstruct import FrameStep
17
 
18
 
19
  def _title(step: FrameStep) -> str:
 
12
  from pathlib import Path
13
  from typing import Union
14
 
15
+ from proteus.game.engine.rendering import COLOR_MAP, frame_to_rgb_array
16
+ from proteus.game.viz.reconstruct import FrameStep
17
 
18
 
19
  def _title(step: FrameStep) -> str:
proteus/{viz โ†’ game/viz}/reconstruct.py RENAMED
@@ -21,11 +21,11 @@ from dataclasses import dataclass
21
 
22
  import numpy as np
23
 
24
- from proteus.grid.ascii_view import frame_to_ascii
25
- from proteus.grid.difficulty import Difficulty
26
- from proteus.grid.game import MotiveGridGame
27
- from proteus.grid.scenario import get_scenario
28
- from proteus.runtime.trace import SessionTrace, TurnTrace
29
 
30
 
31
  class TraceReconstructionError(RuntimeError):
 
21
 
22
  import numpy as np
23
 
24
+ from proteus.game.engine.ascii_view import frame_to_ascii
25
+ from proteus.game.engine.difficulty import Difficulty
26
+ from proteus.game.engine.grid import MotiveGridGame
27
+ from proteus.game.scenarios.base import get_scenario
28
+ from proteus.game.runtime.trace import SessionTrace, TurnTrace
29
 
30
 
31
  class TraceReconstructionError(RuntimeError):
proteus/{viz โ†’ game/viz}/terminal.py RENAMED
@@ -15,8 +15,8 @@ from __future__ import annotations
15
  import time
16
  from typing import Callable, Optional
17
 
18
- from proteus.arc_grid.rendering import COLOR_MAP, hex_to_rgb, rgb_to_ansi
19
- from proteus.viz.reconstruct import FrameMeta, FrameStep
20
 
21
  _RESET = "\033[0m"
22
  _BLOCK = "โ–ˆโ–ˆ"
 
15
  import time
16
  from typing import Callable, Optional
17
 
18
+ from proteus.game.engine.rendering import COLOR_MAP, hex_to_rgb, rgb_to_ansi
19
+ from proteus.game.viz.reconstruct import FrameMeta, FrameStep
20
 
21
  _RESET = "\033[0m"
22
  _BLOCK = "โ–ˆโ–ˆ"
proteus/grid/__init__.py DELETED
@@ -1,10 +0,0 @@
1
- """proteus.grid โ€” the motive_grid scenario family (ported).
2
-
3
- Importing this package imports :mod:`proteus.grid.scenarios`, whose
4
- ``@register_scenario`` decorators populate the scenario registry so
5
- ``get_scenario("predator_evade")`` resolves.
6
- """
7
-
8
- from proteus.grid import scenarios # noqa: F401 โ€” side-effect: populate registry
9
-
10
- __all__ = ["scenarios"]
 
 
 
 
 
 
 
 
 
 
 
proteus/shared/__init__.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ """proteus.shared โ€” cross-cutting vocabulary shared by game and web.
2
+
3
+ Skeleton for now. Future home for trace/data models hoisted out of
4
+ game.runtime to break the game.runtime <-> game.metrics package cycle
5
+ (see 2026-06-02-proteus-game-web-restructure-design.md ยง6.1).
6
+ """