poseres 2.2.0__tar.gz → 2.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {poseres-2.2.0/src/poseres.egg-info → poseres-2.3.0}/PKG-INFO +1 -1
- {poseres-2.2.0 → poseres-2.3.0}/pyproject.toml +1 -1
- {poseres-2.2.0 → poseres-2.3.0/src/poseres.egg-info}/PKG-INFO +1 -1
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/action/recipe.py +82 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/anatomy/minecraft/anatomy.py +21 -1
- {poseres-2.2.0 → poseres-2.3.0}/LICENSE +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/README.md +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/setup.cfg +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/poseres.egg-info/SOURCES.txt +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/poseres.egg-info/dependency_links.txt +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/poseres.egg-info/entry_points.txt +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/poseres.egg-info/requires.txt +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/poseres.egg-info/top_level.txt +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/__init__.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/_deprecation.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/action/__init__.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/action/policy.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/anatomy/__init__.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/anatomy/body.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/anatomy/gymnasium_body.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/anatomy/minecraft/__init__.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/anatomy/minecraft/protocol.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/anatomy/minecraft/transport.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/anatomy/ros2/__init__.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/anatomy/ros2/body.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/anatomy/ros2/fake.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/anatomy/ros2/specs.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/anatomy/ros2/transport.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/config.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/core/__init__.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/core/bus.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/core/contracts.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/core/engine.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/core/frame.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/core/policies.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/core/scorer.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/dash/__init__.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/dash/cli.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/dash/model.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/dash/page.html +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/dash/server.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/examples/__init__.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/examples/rover/__init__.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/examples/rover/cli.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/examples/rover/viewer.html +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/examples/rover/viewer.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/examples/rover/world.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/flush/__init__.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/flush/cli.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/harness/__init__.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/harness/acceptance.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/harness/agency.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/harness/cli.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/harness/ladder.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/harness/report.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/harness/runner.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/harness/scale.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/harness/scan.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/harness/seeding.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/motivation/__init__.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/motivation/context.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/motivation/drive.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/nats/__init__.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/nats/control.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/nats/fake.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/nats/store.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/nats/subjects.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/nats/tap.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/nats/transport.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/persistence/__init__.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/persistence/brain_cli.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/persistence/portable.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/persistence/snapshot.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/persistence/store.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/telemetry/__init__.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/telemetry/recorder.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/world/__init__.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/world/event_source.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/src/pra/world/ladder.py +0 -0
- {poseres-2.2.0 → poseres-2.3.0}/tests/test_hq_structure.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "poseres"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.3.0"
|
|
8
8
|
description = "Pose Resolution Architecture — validation harness and batched in-memory core"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
# >=3.12 since feature 013: ROS 2 LTS containers bind rclpy to Ubuntu 24.04's
|
|
@@ -13,6 +13,19 @@ held at bar, 20/24 provably recipe-led.
|
|
|
13
13
|
Recipes are policy-side state, deliberately not snapshot state in v1: they
|
|
14
14
|
are reconstructible from kept demonstrations (the feature-041 spec records
|
|
15
15
|
the assumption).
|
|
16
|
+
|
|
17
|
+
Place-keyed futility (feature 045; the-long-carry, episode 0120): without
|
|
18
|
+
a disconfirmation pathway the selection argmax is stateless and the body
|
|
19
|
+
pressed a closed gate for 4,672 of 6,000 life-steps. The measured repair
|
|
20
|
+
(rig prototype K=200/W=800: parking abolished, the revive-peek-wander
|
|
21
|
+
loop emerged, first brain-driven lap crossings) ships here keyed to the
|
|
22
|
+
PLACE — a stalled pointer poisons the quantized subgoal it points at, and
|
|
23
|
+
every recipe currently pointing there is ineligible together until the
|
|
24
|
+
poison expires. Both refuted forms carried numbers: per-recipe erosion
|
|
25
|
+
thrashed at the poison boundary (556 die/revive events in one life) and
|
|
26
|
+
per-recipe hysteresis fell back through the cohort of near-identical
|
|
27
|
+
recipes. Futility state follows the recipe rule above: policy-side, not
|
|
28
|
+
snapshot state.
|
|
16
29
|
"""
|
|
17
30
|
|
|
18
31
|
from __future__ import annotations
|
|
@@ -82,6 +95,20 @@ class RecipePolicy(CompletionItchPolicy):
|
|
|
82
95
|
added terms are inert and the policy degrades to its parent. Bounded
|
|
83
96
|
watch counters: ``advance_events`` (subgoal pointer progress) and
|
|
84
97
|
``out_of_context`` (no recipe step within 2 blocks — the parrot watch).
|
|
98
|
+
|
|
99
|
+
Place-keyed futility (feature 045; episode 0120 measured, module
|
|
100
|
+
docstring): with ``futility_k > 0``, ``futility_k`` consecutive
|
|
101
|
+
followed steps without pointer advance poison the pointed place —
|
|
102
|
+
the subgoal position rounded to the block grid — for ``futility_w``
|
|
103
|
+
selection steps; recipes whose pointer currently resolves to a
|
|
104
|
+
poisoned place are ineligible, and with none eligible the policy is
|
|
105
|
+
exactly its parent (the wander phase). Expiry is a clean peek: the
|
|
106
|
+
stall count restarts, so re-poisoning takes ``futility_k`` fresh
|
|
107
|
+
steps — the re-check cadence comes from the constants alone. The
|
|
108
|
+
ONLY futility state is per-place (both per-recipe forms are the
|
|
109
|
+
measured failure modes); ``futility_k = 0`` (default) is bit-exact
|
|
110
|
+
pre-045 behavior, RNG stream included. Watch counters:
|
|
111
|
+
``fatigue_events`` (poisons created), ``revive_events`` (expired).
|
|
85
112
|
"""
|
|
86
113
|
|
|
87
114
|
def __init__(
|
|
@@ -102,6 +129,8 @@ class RecipePolicy(CompletionItchPolicy):
|
|
|
102
129
|
deficit_kappa: float = 0.0,
|
|
103
130
|
commit_kappa: float = 0.0,
|
|
104
131
|
explore_defers_holds: bool = False,
|
|
132
|
+
futility_k: int = 0,
|
|
133
|
+
futility_w: int = 800,
|
|
105
134
|
):
|
|
106
135
|
super().__init__(
|
|
107
136
|
params,
|
|
@@ -121,9 +150,21 @@ class RecipePolicy(CompletionItchPolicy):
|
|
|
121
150
|
self.lambda_r = float(lambda_r)
|
|
122
151
|
self.position_indices = (int(position_indices[0]), int(position_indices[1]))
|
|
123
152
|
self.position_scale = float(position_scale)
|
|
153
|
+
fk, fw = float(futility_k), float(futility_w)
|
|
154
|
+
if not np.isfinite(fk) or fk < 0.0 or fk != int(fk):
|
|
155
|
+
raise ValueError(f"RecipePolicy: futility_k {futility_k} must be a finite integer >= 0")
|
|
156
|
+
if not np.isfinite(fw) or fw <= 0.0 or fw != int(fw):
|
|
157
|
+
raise ValueError(f"RecipePolicy: futility_w {futility_w} must be a finite integer > 0")
|
|
158
|
+
self.futility_k = int(fk)
|
|
159
|
+
self.futility_w = int(fw)
|
|
124
160
|
self.advance_events = 0
|
|
125
161
|
self.out_of_context = 0
|
|
162
|
+
self.fatigue_events = 0
|
|
163
|
+
self.revive_events = 0
|
|
126
164
|
self._prev_ptr = -1
|
|
165
|
+
self._futility_step = 0
|
|
166
|
+
self._poisons: dict[tuple[int, int], int] = {} # place -> last poisoned step
|
|
167
|
+
self._stall: tuple[tuple[int, int], int] | None = None # (place, count)
|
|
127
168
|
self._ctx: PolicyContext | None = None
|
|
128
169
|
self._subgoal: tuple[float, float] | None = None
|
|
129
170
|
self.potential_of = self._recipe_hold
|
|
@@ -132,10 +173,45 @@ class RecipePolicy(CompletionItchPolicy):
|
|
|
132
173
|
ix, iz = self.position_indices
|
|
133
174
|
return float(obs[ix]) * self.position_scale, float(obs[iz]) * self.position_scale
|
|
134
175
|
|
|
176
|
+
def _place_key(self, pos: tuple[float, float]) -> tuple[int, int]:
|
|
177
|
+
return int(round(pos[0])), int(round(pos[1]))
|
|
178
|
+
|
|
179
|
+
def _pointed_place(self, ctx: PolicyContext, recipe: Recipe) -> tuple[int, int]:
|
|
180
|
+
"""Where this recipe's pointer currently resolves — the
|
|
181
|
+
side-effect-free twin of :meth:`_point_subgoal`'s arithmetic."""
|
|
182
|
+
cur = self._pos(ctx.observation)
|
|
183
|
+
dists = [
|
|
184
|
+
max(abs(self._pos(o)[0] - cur[0]), abs(self._pos(o)[1] - cur[1])) for o in recipe.steps
|
|
185
|
+
]
|
|
186
|
+
ptr = min(int(np.argmin(dists)) + 1, len(recipe.steps) - 1)
|
|
187
|
+
return self._place_key(self._pos(recipe.steps[ptr]))
|
|
188
|
+
|
|
189
|
+
def _expire_poisons(self) -> None:
|
|
190
|
+
for place in [p for p, last in self._poisons.items() if last < self._futility_step]:
|
|
191
|
+
del self._poisons[place]
|
|
192
|
+
self.revive_events += 1
|
|
193
|
+
|
|
194
|
+
def _track_stall(self, place: tuple[int, int], advanced: bool) -> None:
|
|
195
|
+
if advanced:
|
|
196
|
+
self._stall = None
|
|
197
|
+
return
|
|
198
|
+
count = self._stall[1] + 1 if self._stall is not None and self._stall[0] == place else 1
|
|
199
|
+
if count >= self.futility_k:
|
|
200
|
+
# dead through step + futility_w inclusive: exactly futility_w
|
|
201
|
+
# ineligible selection steps, then the peek
|
|
202
|
+
self._poisons[place] = self._futility_step + self.futility_w
|
|
203
|
+
self._stall = None
|
|
204
|
+
self.fatigue_events += 1
|
|
205
|
+
else:
|
|
206
|
+
self._stall = (place, count)
|
|
207
|
+
|
|
135
208
|
def _select_recipe(self, ctx: PolicyContext) -> Recipe | None:
|
|
136
209
|
best, best_v = None, -np.inf
|
|
137
210
|
weight = 0.0 if self.label_index is None else self._label_weight(ctx.observation)
|
|
211
|
+
poisons = self._poisons if self.futility_k else None
|
|
138
212
|
for r in self.memory.recipes:
|
|
213
|
+
if poisons and self._pointed_place(ctx, r) in poisons:
|
|
214
|
+
continue
|
|
139
215
|
v = ctx.drive_value_of(r.terminal)
|
|
140
216
|
if self.label_index is not None:
|
|
141
217
|
v += weight * float(r.terminal[self.label_index])
|
|
@@ -171,6 +247,12 @@ class RecipePolicy(CompletionItchPolicy):
|
|
|
171
247
|
|
|
172
248
|
def select_action(self, context: PolicyContext, rng) -> int:
|
|
173
249
|
self._ctx = context
|
|
250
|
+
if self.futility_k:
|
|
251
|
+
self._futility_step += 1
|
|
252
|
+
self._expire_poisons()
|
|
253
|
+
adv_before = self.advance_events
|
|
174
254
|
recipe = self._select_recipe(context)
|
|
175
255
|
self._subgoal = None if recipe is None else self._point_subgoal(context, recipe)
|
|
256
|
+
if self.futility_k and self._subgoal is not None:
|
|
257
|
+
self._track_stall(self._place_key(self._subgoal), self.advance_events > adv_before)
|
|
176
258
|
return super().select_action(context, rng)
|
|
@@ -149,12 +149,26 @@ _AIM = SensorSpec(
|
|
|
149
149
|
labels=tuple(f"s{k}" for k in range(8)) + ("drop",),
|
|
150
150
|
)
|
|
151
151
|
|
|
152
|
+
# The peers sense (research topic lean-worlds, licensed by Bar L1,
|
|
153
|
+
# 2026-08-17): the nearest OTHER body, in the drops sense's exact
|
|
154
|
+
# grammar — presence, egocentric bearing, distance, count, and the
|
|
155
|
+
# appearance signature of the world's own username (identity as
|
|
156
|
+
# property; hashed, never parsed). Opt-in; appended LAST so every
|
|
157
|
+
# shipped offset is unchanged.
|
|
158
|
+
_PEERS = SensorSpec(
|
|
159
|
+
id="peers",
|
|
160
|
+
topic="peers",
|
|
161
|
+
width=8,
|
|
162
|
+
labels=("present", "sin_b", "cos_b", "dist", "count", "sig0", "sig1", "sig2"),
|
|
163
|
+
)
|
|
164
|
+
|
|
152
165
|
|
|
153
166
|
def c1_anatomy(
|
|
154
167
|
crafting: bool = True,
|
|
155
168
|
survival: bool | None = None,
|
|
156
169
|
flood: bool | None = None,
|
|
157
170
|
aim: str | None = None,
|
|
171
|
+
peers: bool = False,
|
|
158
172
|
) -> tuple[list[SensorSpec], list[ActuatorSpec]]:
|
|
159
173
|
"""The (sensors, actuators) lists `Ros2Body.factory` expects.
|
|
160
174
|
|
|
@@ -167,7 +181,9 @@ def c1_anatomy(
|
|
|
167
181
|
``crafting=False``: the exact feature-027 body (14/8).
|
|
168
182
|
``flood=True``/``aim="worth"``: the instrument senses individually
|
|
169
183
|
(module doc); ``aim="salience"`` is bridge behavior only, the
|
|
170
|
-
declaration byte-identical to ``aim=""``.
|
|
184
|
+
declaration byte-identical to ``aim=""``. ``peers=True`` appends
|
|
185
|
+
the peers sense LAST (research topic lean-worlds; ships into the
|
|
186
|
+
default only on promotion) — the 94/13 instrument body.
|
|
171
187
|
"""
|
|
172
188
|
if survival is None:
|
|
173
189
|
blessed = crafting # the zero-override default: design 0015's stack
|
|
@@ -189,6 +205,8 @@ def c1_anatomy(
|
|
|
189
205
|
raise ValueError(f"unknown aim form {aim!r}: expected '', 'salience', or 'worth'")
|
|
190
206
|
if aim and not survival:
|
|
191
207
|
raise ValueError("the aim is a survival-instrument sense: it needs the distal body")
|
|
208
|
+
if peers and not survival:
|
|
209
|
+
raise ValueError("the peers sense is a survival-instrument sense: it needs the distal body")
|
|
192
210
|
sensors = list(_BASE_SENSORS) + (list(_PROPERTY_SENSORS) if crafting else [])
|
|
193
211
|
if survival:
|
|
194
212
|
sensors = [_SURVIVAL_HAND if s.id == "hand" else s for s in sensors]
|
|
@@ -197,6 +215,8 @@ def c1_anatomy(
|
|
|
197
215
|
sensors.append(_FLOOD)
|
|
198
216
|
if aim == "worth":
|
|
199
217
|
sensors.append(_AIM)
|
|
218
|
+
if peers:
|
|
219
|
+
sensors.append(_PEERS)
|
|
200
220
|
presets = _BASE_PRESETS + (_GRID_PRESETS if crafting else ())
|
|
201
221
|
presets += _SURVIVAL_PRESETS if survival else ()
|
|
202
222
|
return sensors, [ActuatorSpec(id="control", topic="control", presets=presets)]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|