Skip to content

Commit 0409e21

Browse files
committed
cleanup: scrub environment-specific references, fix lint, update line numbers
1 parent 853dc89 commit 0409e21

11 files changed

Lines changed: 21 additions & 25 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
![Zero Dependencies](https://img.shields.io/badge/Dependencies-Zero-brightgreen.svg)
55
![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)
66
![CI](https://github.com/tmcarmichael/compass-core/actions/workflows/ci.yml/badge.svg)
7-
![Coverage](<https://img.shields.io/badge/Coverage-71%25_(21.5K_measured)-blue.svg>)
7+
[![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/tmcarmichael/COVERAGE_GIST_ID/raw/coverage.json)](https://github.com/tmcarmichael/compass-core/actions/workflows/ci.yml)
88

99
A layered decision architecture for intelligent behavior in a real-time 3D world.
1010

@@ -16,7 +16,7 @@ Compass is a control architecture for agents that must perceive, decide, and act
1616

1717
The architecture evolved in a legacy 3D MMORPG sandbox. It progressed from a monolith through reactive rules, state-machine routines, and utility scoring before arriving at goal-oriented planning. Each transition came when the previous approach broke against the world's complexity.
1818

19-
> **Scope.** This is a cleaned extraction from a private working repo, published as an architecture reference. Live runtime config, environment assets, and operational glue are intentionally omitted. See [docs/samples/](docs/samples/) for real session output.
19+
> **Scope.** This is a cleaned extraction from a private working repo, published as an architecture reference. Live runtime config, environment assets, and operational glue are intentionally omitted. See [docs/samples/](docs/samples/) for real session output. For a step-by-step trace from perception to motor output, see [`docs/walkthrough.md`](docs/walkthrough.md).
2020
2121
---
2222

@@ -220,7 +220,7 @@ All samples in [docs/samples/](docs/samples/) are real output from live sessions
220220
| [Forensics buffer](docs/samples/forensics-ring-buffer.md) | 300-tick ring buffer dump: skeleton aggro interrupts spell memorization, FLEE fires within one tick |
221221
| [Learned encounter data](docs/samples/learned-encounter-data.md) | Cross-session improvement: grade B → A, fight duration 29.5s → 15.9s, auto-tuned parameters drifting from defaults |
222222
| [Fight event](docs/samples/structured-fight-event.md) | Structured `fight_end` event with all 20 fields and embedded world snapshot |
223-
| [Convergence](docs/samples/convergence.md) | 10-session headless run: fight duration drops 53% as encounter history accumulates and cost functions self-correct |
223+
| [Convergence](docs/samples/convergence.md) | 10-session headless run: fight duration drops 53% as encounter history accumulates and cost functions self-correct |
224224
| [Ablation results](docs/samples/ablation-results.md) | Learning vs. defaults: 97% GOAP cost error reduction, 25x danger discrimination, weight tuning stability |
225225

226226
---

docs/architecture.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ Strategy selection uses learned encounter history when available; after 5+ encou
273273

274274
### Terrain
275275

276-
Zone geometry is parsed from the game client's asset files own 3D asset files. The parsing pipeline extracts walkable surfaces and produces heightmap caches at 1-unit resolution.
276+
Zone geometry is parsed from the game client's own 3D asset files. The parsing pipeline extracts walkable surfaces and produces heightmap caches at 1-unit resolution.
277277

278278
Each cell in the heightmap stores:
279279

docs/walkthrough.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ What happens in one tick of the 10 Hz brain loop, traced through the actual sour
66

77
## 1. Clock gate
88

9-
[`brain/runner/loop.py:552`](../src/brain/runner/loop.py) -- The `TickClock` blocks until the next 100ms boundary. When it releases, the tick counter increments and the loop begins.
9+
[`brain/runner/loop.py:541`](../src/brain/runner/loop.py) -- The `TickClock` blocks until the next 100ms boundary. When it releases, the tick counter increments and the loop begins.
1010

1111
```
1212
_clock.wait_for_next_tick()
@@ -16,25 +16,25 @@ The clock measures `dt` (actual elapsed time since last tick). At 10 Hz with no
1616

1717
## 2. Perception snapshot
1818

19-
[`brain/runner/loop.py:557-563`](../src/brain/runner/loop.py) -- `_tick_pre_state` calls `reader.read_state(include_spawns=True)`, which traverses the game client's internal pointer chains via `ReadProcessMemory` and returns a frozen `GameState` dataclass. This snapshot is immutable after creation: the brain thread produces it, every subsequent step consumes it, no locks needed.
19+
[`brain/runner/loop.py:546`](../src/brain/runner/loop.py) -- `_tick_pre_state` calls `reader.read_state(include_spawns=True)`, which traverses the game client's internal pointer chains via `ReadProcessMemory` and returns a frozen `GameState` dataclass. This snapshot is immutable after creation: the brain thread produces it, every subsequent step consumes it, no locks needed.
2020

2121
The `GameState` contains: player position (x, y, z), HP/mana current and max, target info, heading, zone ID, combat flag, sitting flag, and a tuple of `SpawnData` for every visible entity.
2222

2323
If the memory read fails (process not responding, pointer chain broken), the tick is skipped entirely -- the brain never evaluates stale state.
2424

2525
## 3. World state update
2626

27-
[`brain/runner/loop.py:570`](../src/brain/runner/loop.py) -- `WorldStateUpdater.update_world_state()` refreshes the derived world model: NPC tracking (who appeared, who moved, who despawned), pet status, threat detection (approaching hostile entities), and health monitoring. This runs before rule evaluation so that rules see current-tick derived state.
27+
[`brain/runner/loop.py:559`](../src/brain/runner/loop.py) -- `WorldStateUpdater.update_world_state()` refreshes the derived world model: NPC tracking (who appeared, who moved, who despawned), pet status, threat detection (approaching hostile entities), and health monitoring. This runs before rule evaluation so that rules see current-tick derived state.
2828

2929
For tick 1147: the world model registers a level-appropriate NPC at 85 units distance that was not present on the previous tick. The threat scanner classifies it as non-hostile (not approaching). The entity enters the world model's tracking table.
3030

3131
## 4. Pre-rule event detection
3232

33-
[`brain/runner/loop.py:581-583`](../src/brain/runner/loop.py) -- Three pre-rule handlers run: XP tracking (records any XP change), add detection (checks if a new NPC is attacking the pet), and auto-engage scanning (detects if the current target changed). These update `AgentContext` sub-state objects before the decision engine reads them.
33+
[`brain/runner/loop.py:570-572`](../src/brain/runner/loop.py) -- Three pre-rule handlers run: XP tracking (records any XP change), add detection (checks if a new NPC is attacking the pet), and auto-engage scanning (detects if the current target changed). These update `AgentContext` sub-state objects before the decision engine reads them.
3434

3535
## 5. Rule evaluation (the decision)
3636

37-
[`brain/runner/loop.py:608`](../src/brain/runner/loop.py) -- `brain.tick(state)` enters the decision engine. Inside [`brain/decision.py:154-161`](../src/brain/decision.py):
37+
[`brain/runner/loop.py:593`](../src/brain/runner/loop.py) -- `_tick_brain` calls `brain.tick(state)`, entering the decision engine. Inside [`brain/decision.py:173-180`](../src/brain/decision.py):
3838

3939
```python
4040
def tick(self, state: GameState) -> None:
@@ -48,7 +48,7 @@ def tick(self, state: GameState) -> None:
4848

4949
### 5a. Rule scan
5050

51-
[`brain/decision.py:163-255`](../src/brain/decision.py) -- At Phase 0 (binary conditions, insertion-order priority), rules evaluate top to bottom. The first rule whose condition returns `True` wins. After a winner is found, remaining rules are skipped.
51+
[`brain/decision.py:182`](../src/brain/decision.py) -- At Phase 0 (binary conditions, insertion-order priority), rules evaluate top to bottom. The first rule whose condition returns `True` wins. After a winner is found, remaining rules are skipped.
5252

5353
For tick 1147, the evaluation cascade looks like this (from the decision receipt in the sample data):
5454

@@ -86,7 +86,7 @@ For this tick: `tab_target()` sends a Tab keypress. The next perception snapshot
8686

8787
## 8. Observability
8888

89-
[`brain/runner/loop.py:614`](../src/brain/runner/loop.py) -- `_tick_record_diag` runs after the brain tick completes:
89+
[`brain/runner/loop.py:599`](../src/brain/runner/loop.py) -- `_tick_record_diag` runs after the brain tick completes:
9090

9191
- **Decision receipt**: a structured record of which rules fired, their scores, the selected routine, lock state, and tick timing. This is the data in [`docs/samples/decision-trace.md`](samples/decision-trace.md).
9292
- **Forensics ring buffer**: the last 300 ticks of brain state, continuously overwritten. On death or crash, this buffer flushes to disk -- 30 seconds of pre-incident telemetry.
@@ -95,7 +95,7 @@ For this tick: `tab_target()` sends a Tab keypress. The next perception snapshot
9595

9696
## 9. Heartbeat
9797

98-
[`brain/runner/loop.py:613`](../src/brain/runner/loop.py) -- The heartbeat timestamp updates. A secondary thread monitors this value; if it goes stale for 10+ seconds, the watchdog triggers recovery (process reconnection or graceful shutdown).
98+
[`brain/runner/loop.py:598`](../src/brain/runner/loop.py) -- The heartbeat timestamp updates. A secondary thread monitors this value; if it goes stale for 10+ seconds, the watchdog triggers recovery (process reconnection or graceful shutdown).
9999

100100
---
101101

src/eq/s3d.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ def __init__(self, path: str | Path) -> None:
2222
self.path = Path(path)
2323
self._entries: dict[str, tuple[int, int]] = {} # name -> (offset, size)
2424
raise NotImplementedError(
25-
"S3DArchive parser stubbed in public release. "
26-
"Provide an environment-specific implementation."
25+
"S3DArchive parser stubbed in public release. Provide an environment-specific implementation."
2726
)
2827

2928
def list_files(self) -> list[str]:

src/eq/wld.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
from dataclasses import dataclass
1212

13-
1413
# ======================================================================
1514
# Data classes
1615
# ======================================================================
@@ -147,8 +146,7 @@ class WLDFile:
147146

148147
def __init__(self, data: bytes) -> None:
149148
raise NotImplementedError(
150-
"WLDFile parser stubbed in public release. "
151-
"Provide an environment-specific implementation."
149+
"WLDFile parser stubbed in public release. Provide an environment-specific implementation."
152150
)
153151

154152
def extract_meshes(self) -> list[Mesh]:

src/perception/struct_validator.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,9 @@ def _check_profile_chain(self) -> CheckResult:
227227
# Step 2: intermediate
228228
intermediate = self._r._read_pointer(ci + offsets.CHARINFO_PROFILE_INDIR)
229229
if intermediate == 0:
230-
return CheckResult(name, False, f"character info+0x{offsets.CHARINFO_PROFILE_INDIR:03X} -> null")
230+
return CheckResult(
231+
name, False, f"character info+0x{offsets.CHARINFO_PROFILE_INDIR:03X} -> null"
232+
)
231233

232234
# Step 3: profile base
233235
profile_base = self._r._read_pointer(intermediate + offsets.PROFILE_PTR_OFFSET)

src/simulator/runner.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,7 @@ def _simulate_encounter_learning(self, scenario: Scenario) -> None:
294294
self._ctx.metrics.total_casts += 2
295295
self._ctx.metrics.routine_counts["PULL"] += 1
296296
self._ctx.metrics.routine_counts["IN_COMBAT"] += 1
297-
self._ctx.metrics.routine_time["PULL"] = (
298-
self._ctx.metrics.routine_time.get("PULL", 0) + 3.0
299-
)
297+
self._ctx.metrics.routine_time["PULL"] = self._ctx.metrics.routine_time.get("PULL", 0) + 3.0
300298
self._ctx.metrics.routine_time["IN_COMBAT"] = (
301299
self._ctx.metrics.routine_time.get("IN_COMBAT", 0) + duration
302300
)

tests/test_eq_parsers.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
load_zone_chr,
2626
)
2727

28-
2928
# ===========================================================================
3029
# zone_chr.py -- data classes (not stubbed)
3130
# ===========================================================================

tests/test_loadout.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import pytest
1111

12-
from eq.spells import SpellDB, SpellRole
12+
from eq.spells import SpellDB
1313

1414
# ---------------------------------------------------------------------------
1515
# Helpers -- reuse the _spell factory
@@ -32,7 +32,7 @@ def _spell_data(
3232
range: int = 200,
3333
recast_ms: int = 0,
3434
):
35-
from eq.spells import ResistType, SpellData, TargetType
35+
from eq.spells import SpellData
3636

3737
if class_levels is None:
3838
class_levels = (255,) * 16

tests/test_race_data.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
from eq.race_data import RACE_NAMES, RaceDB, RaceModelData, load_race_data
1111

12-
1312
# ---------------------------------------------------------------------------
1413
# RACE_NAMES static lookup (stubbed to empty)
1514
# ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)