ADR-095 - Subspace Anchor Providers, Near-Teleport Primitives, and External Verifier Perimeter Extraction¶
Status: Accepted (2026-09-22). Record reconstructed 2026-10-05 from the shipped implementation; the original file was never committed. Date: 2026-09-22 Extends: ADR-093 (Declarative Scripted Actions and Subspace Placement) Related: ADR-079 (Cause-Based TTL and Spatial Memory Learning), ADR-097 (Per-Action Caches and Bounded Retries), ADR-069 (Claim Addon), S-003, S-004, S-005
Context¶
ADR-093 places a group of participants into safe slots around one anchor coordinate (X0, Z0). Its MVP drew that anchor only from the region's pre-warmed queue. Competitor "near" teleports (nearplayer, near a claim, near a landmark) need other anchor origins, but they must keep the core guarantees: no main-thread chunk I/O (S-005), no landing inside protected land (S-003), and no silent failure (S-004).
A claim-adjacent anchor also needs a claim position. Inline claim-plugin calls in the pipeline are prohibited (S-003 common wrong move), but spatial memory already records every external-verifier rejection under the safetyExternal fail cause (ADR-079).
Decision¶
AnchorSourceSPI (rtp-api,io.github.dailystruggle.rtp.api.group). A@PublicApifunctional interface returningCompletableFuture<RTPCoords>; resolution never blocks the main thread. Built-in factories:
| Factory | Origin |
|---|---|
regionQueue() (default) |
One verified location from the region's shared kept/hot queue. |
fixed(coords) |
A configured landmark coordinate. |
entity(supplier) |
A live entity / player position. |
claimHazard() |
A claim perimeter recalled from spatial memory (item 4). |
claimBoundary(boundary) |
A ClaimBoundary supplied by a claim integration. |
- Resolution (
rtp-core,SubspaceAnchorResolver.resolveAnchor). regionQueuepollsRegionQueueManager.poll(null)(no owning player;pollshall not throw on anulluuid) and falls back to on-demandRegion.getLocationwhen the queue is empty.claimBoundaryresolves throughClaimAnchoredRegionTracker(centre preservation) and ingests the region's known hazard memory inside the boundary.- Other sources resolve asynchronously; a missing world name inherits the region's world.
-
Every null or exceptional result is logged and surfaces as a placement failure (
NO_ANCHOR), never a stalled future (S-004). -
YAML selector (
placement.anchor,ActionManager.resolveAnchorSource).
| Value(s) | Source | When unresolved |
|---|---|---|
regionQueue (default, and any unknown value incl. scatter) |
regionQueue() |
on-demand generation |
fixed, location, landmark |
fixed from anchorX/Y/Z/World (context metadata first, then placement parameters) |
regionQueue() |
entity, player, nearplayer |
entity; with no coordinates, a random online non-participant |
fails closed (no silent random fallback) |
claim, claimhazard, nearclaim |
claimHazard() |
NO_ANCHOR |
claimboundary, faction |
claimBoundary via context metadata or RTPAPI.hooks.claimBoundaries() (namespace factions for faction, overridable by namespace) |
claimHazard() |
-
External verifier perimeter extraction.
SubspaceAnchorResolver.resolveClaimPerimeterscans the parentMemoryShape's bad-run snapshot (badKeysSnapshot/badCausesSnapshot) for asafetyExternalrun and anchors at that chunk's centre. Core thus learns claim positions from verifier rejections without calling claim plugins; slot validation still runs every global verifier, so S-003 holds for each landing slot. -
Near-teleport primitives are actions, not commands.
nearplayer,nearclaimandlocationship as bundled sample definitions (definitions/actions/*.yml) on the ADR-093 engine; no dedicated command or pipeline exists for them.
Alternatives Considered¶
| Alternative | Why Rejected |
|---|---|
Dedicated /rtp near* commands with their own pipelines |
Duplicates queueing, validation and confinement; ADR-093 is capability, not catalogue. |
| Query claim plugins for perimeters inside core | Violates the S-003 boundary; claim integrations live in the bundled claim addon (ADR-069). |
Fall back to a random region anchor when nearplayer has no target |
Silently changes the action's meaning; fail closed instead (S-004). |
Consequences¶
- Positive: One placement engine serves standard group, near-player, near-claim and landmark actions; addons can supply custom
AnchorSourceimplementations; claim anchoring needs no claim-plugin calls in core. - Negative / Trade-offs:
claimHazardreturns the first rememberedsafetyExternalrun, so it needs prior rejections in that region and is not uniformly distributed across claims.scatteris an alias of the region-queue anchor, not a separate world-wide sampler;docs/admin/ACTIONS.mdshould describe it that way.
References¶
rtp-api:AnchorSource,GroupPlacementRequest,GroupProfileSpec,ClaimBoundary,ClaimBoundaryRegistry.rtp-core:SubspaceAnchorResolver,ActionManager.resolveAnchorSource,ClaimAnchoredRegionTracker,GroupPlacementDispatcher.- Tests:
ActionManagerTest#testAnchorSourceSelection,SampleActionE2ETest,SampleActionPlacementChartTest. docs/architecture/14-group-placement-anchor-flow.md,docs/admin/ACTIONS.md.