Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 103 additions & 3 deletions .github/workflows/core-tip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ jobs:
RUSTUP_TOOLCHAIN: 1.93.0
SPACETIME_VERSION: 2.7.1
SPACETIME_ARCHIVE_SHA256: 9b58192135733083479f30aba47dbbbc79b51db368c46cc221baa663e9c3a2c1
CARGO_BUILD_JOBS: 2
CARGO_INCREMENTAL: 0
CARGO_PROFILE_DEV_DEBUG: 0
CARGO_PROFILE_TEST_DEBUG: 0
steps:
- name: Check out Packages
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand Down Expand Up @@ -179,12 +183,108 @@ jobs:
--locked --release --target wasm32-unknown-unknown -p lyracore-module --features=debug_reducers
cp "$CARGO_TARGET_DIR/wasm32-unknown-unknown/release/lyracore_module.wasm" "$RUNNER_TEMP/playerbots-preceding.wasm"
echo "PLAYERBOTS_PRECEDING_WASM=$RUNNER_TEMP/playerbots-preceding.wasm" >> "$GITHUB_ENV"
- name: Check out the merged PB-002 Module source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: LyraCoreProject/LyraCore
ref: e6a755db0a150bbf73ad97b972fe829f20f6816c
path: preceding-pb002-core
persist-credentials: false
- name: Check out the merged PB-002 Package source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: LyraCoreProject/packages
ref: 155c9e401afb06d5731acedf8fc35a81dbe4aaa6
path: preceding-pb002-collection
persist-credentials: false
- name: Build the merged PB-002 Wasm for populated companion migration
working-directory: preceding-pb002-core
run: |
export CARGO_TARGET_DIR="$GITHUB_WORKSPACE/preceding-pb002-core/target"
cargo clean --manifest-path "$GITHUB_WORKSPACE/preceding-pb002-core/Cargo.toml" -p lyracore-module
"$GITHUB_WORKSPACE/preceding-pb002-collection/.github/check-core-tip.sh" "$GITHUB_WORKSPACE/preceding-pb002-core" \
cargo build --manifest-path "$GITHUB_WORKSPACE/preceding-pb002-core/Cargo.toml" \
--locked --release --target wasm32-unknown-unknown -p lyracore-module --features=debug_reducers
cp "$CARGO_TARGET_DIR/wasm32-unknown-unknown/release/lyracore_module.wasm" "$RUNNER_TEMP/playerbots-pb002-preceding.wasm"
python3 - "$RUNNER_TEMP/playerbots-pb002-preceding.wasm" \
"$GITHUB_WORKSPACE/preceding-pb002-core" \
"$GITHUB_WORKSPACE/preceding-pb002-collection" \
"$RUNNER_TEMP/playerbots-pb002-preceding-inputs.json" <<'PY'
import datetime
import hashlib
import json
import pathlib
import subprocess
import sys

wasm_path, core_path, collection_path, manifest_path = map(pathlib.Path, sys.argv[1:])

def git(path, *args):
return subprocess.run(
["git", *args], cwd=path, check=True, text=True, capture_output=True
).stdout.strip()

if git(core_path, "status", "--porcelain"):
raise SystemExit("the preceding PB-002 Module checkout is dirty")
if git(collection_path, "status", "--porcelain"):
raise SystemExit("the preceding PB-002 Package checkout is dirty")

wasm = wasm_path.read_bytes()
rust_detail = subprocess.run(
["rustc", "--version"], check=True, text=True, capture_output=True
).stdout.strip()
spacetime_detail = subprocess.run(
["spacetime", "--version"], check=True, text=True, capture_output=True
).stdout.strip()
installed_packages = sorted(
path.name
for root in (core_path / "packages", collection_path)
for path in root.iterdir()
if path.is_dir() and not path.name.startswith(".")
)
manifest = {
"created_at": datetime.datetime.now(datetime.timezone.utc).isoformat(),
"core": git(core_path, "rev-parse", "HEAD"),
"collection": git(collection_path, "rev-parse", "HEAD"),
"core_tree": git(core_path, "rev-parse", "HEAD^{tree}"),
"collection_tree": git(collection_path, "rev-parse", "HEAD^{tree}"),
"playerbots_tree": git(collection_path, "rev-parse", "HEAD:playerbots"),
"core_dirty": False,
"collection_dirty": False,
"rust": rust_detail.split()[1],
"rust_detail": rust_detail,
"spacetimedb": spacetime_detail.split("spacetimedb tool version ", 1)[1].split(";", 1)[0],
"spacetimedb_detail": spacetime_detail,
"target": "wasm32-unknown-unknown",
"profile": "release",
"features": ["debug_reducers"],
"installed_packages": installed_packages,
"wasm_bytes": len(wasm),
"wasm_sha256": hashlib.sha256(wasm).hexdigest(),
"package_content_identity": "33fcb8a217aad84f46f9ad65efdad23be24bad8e29828777de7c7e6469417161",
"verification": "Build input from clean merged PB-002 checkouts. The consumer verifies the source identities, Package content, and this environment's Wasm digest before publish and populated upgrade.",
}
manifest_path.write_text(json.dumps(manifest, indent=2) + "\n")
PY
echo "PLAYERBOTS_COMPANION_PRECEDING_WASM=$RUNNER_TEMP/playerbots-pb002-preceding.wasm" >> "$GITHUB_ENV"
echo "PLAYERBOTS_COMPANION_PRECEDING_MANIFEST=$RUNNER_TEMP/playerbots-pb002-preceding-inputs.json" >> "$GITHUB_ENV"
echo "PLAYERBOTS_COMPANION_PRECEDING_CORE=$GITHUB_WORKSPACE/preceding-pb002-core" >> "$GITHUB_ENV"
echo "PLAYERBOTS_COMPANION_PRECEDING_COLLECTION=$GITHUB_WORKSPACE/preceding-pb002-collection" >> "$GITHUB_ENV"
- name: Run the real Module and Package action fixture
working-directory: lyracore
env:
CARGO_TARGET_DIR: ${{ github.workspace }}/lyracore/target
run: |
cargo clean --manifest-path "$GITHUB_WORKSPACE/lyracore/Cargo.toml" -p lyracore-module
./collection/.github/check-core-tip.sh "$GITHUB_WORKSPACE/lyracore" \
cargo test --manifest-path "$GITHUB_WORKSPACE/lyracore/Cargo.toml" \
-p lyracore-module --test playerbots_rewrite -- --ignored --test-threads=1
"$GITHUB_WORKSPACE/collection/.github/check-core-tip.sh" "$GITHUB_WORKSPACE/lyracore" \
bash -eu -o pipefail -c '
cargo build --manifest-path "$GITHUB_WORKSPACE/lyracore/Cargo.toml" \
--locked --release --target wasm32-unknown-unknown \
-p lyracore-module --features=debug_reducers
cargo test --manifest-path "$GITHUB_WORKSPACE/lyracore/Cargo.toml" \
-p lyracore-module --test playerbots_rewrite --test playerbots_companion \
--no-fail-fast -- --ignored --test-threads=1
'
- name: Upload fixture inputs and Standalone logs
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
Expand Down
46 changes: 37 additions & 9 deletions playerbots/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -421,13 +421,26 @@ the Package cast identity or movement start time, so it preserves a human's late
can resume after ownership ends. The ownership Gate permits an absent body for Legacy restoration;
group admission additionally requires a live entity.

The Cohort behavior in this revision returns to the roster's home point. It retains that objective
while healing itself with a known supported rotation spell, defending against damage, or fleeing
at its configured health threshold. Companion orders and quest catalog execution remain separate
work. The existing Legacy policy remains available under its explicit selector.
The Cohort behavior follows the durable leader of a human-led party. It refreshes the leader's
position without replacing the companion objective, so a moving leader cannot restart a retained
cast. An injured same-partition party member outranks follow when the Priest knows a supported
healing rotation spell. Range or line of sight becomes a movement prerequisite that retains the
member identity across movement legs even if another member becomes more injured. A blocked route
remains visible as a CastingPosition wait. A completed, cancelled, or refused cast releases the
foreground action so the next pass can heal again or resume follow.
An ungrouped Cohort returns to its roster home point. A bot-led party does not activate companion
control. A membership whose parent Group is unavailable holds the existing objective and records the
typed failure. The existing Legacy policy remains available under its explicit selector.

A dead companion retains its role and objective while it releases and uses the spirit healer. Once
alive, it regroups with the same leader. Survival movement has priority over healing while the bot
is away from a safe destination. At a reached destination, survival is complete and usable recovery
can run. If recovery is missing, the runner leaves lower-priority maintenance reachable instead of
hiding it behind a Survival Hold.

Recovery scans at most 24 indexed healing rotation rows and revalidates at most two retained
rows per pass. The separate
rows per pass. Learned channels are excluded during that scan, before priority chooses the retained
rotation. The separate
`pkg_playerbots_recovery_scan` explanation records its indexed cursor, scanned row count,
and Pending or Complete stage. A first incomplete scan selects Recovery Hold. A completed missing-spell result keeps lower-priority
actions eligible while later scans continue. Completed
Expand All @@ -452,21 +465,36 @@ One foreground action retains the controller generation and partition. A higher-
cancels incompatible work before starting. Pending casts retain the core scheduled identity and
refresh its current due time after direct-damage pushback. After a movement request, arrival requires a later position
observation. Ten seconds without movement records a failure; three failed intervals defer the
same destination for 30 seconds. Deferred keys include map, instance and optional navigation
coverage generation. A coverage change invalidates the prior destination decision.
same return-home destination for 30 seconds. Companion movement keeps the leader identity and
retries from current durable party facts instead. Deferred keys include map, instance and optional
navigation coverage generation. A coverage change invalidates the prior destination decision.

The selector allows at most 24 candidates, depth four, 16 transitions and one route request with
4096 expansions per decision. These limits also apply to prerequisites, alternatives and continuers.
Strategies use typed triggers and integer priority adjustments. Each Candidate carries a typed action
payload, reason and objective identity. Movement names Home or an Entity; Cast carries its spell and
target; Attack carries its target. There is no string registry.
payload, reason and objective identity. Movement names Home, an Entity, or an ally whose casting
position is required. Cast carries its spell and target; Attack carries its target. There is no
string registry.

The migration appends `controller = Legacy` and `scheduler_lag_micros = 0` to the roster and adds
runner, recovery scan and scheduler tables. Existing goals and action observations keep their schema and meaning.
The roster selector travels with the Character; runner observations and foreground work do not.
The Character delete operation removes the runner and recovery scan rows. Production publication still requires the
schema review described in LyraCore's `docs/danger-zones.md`.

The companion migration appends nullable leader and injured-member identities to each runner row.
Its populated upgrade case starts from merged PB-002 core
`e6a755db0a150bbf73ad97b972fe829f20f6816c` and collection
`155c9e401afb06d5731acedf8fc35a81dbe4aaa6`. It publishes a retained return-home objective and cast
foreground, upgrades the same private Standalone, and checks that both values survive while the new
identity fields receive their null defaults. Set `PLAYERBOTS_COMPANION_PRECEDING_WASM` to that
immutable Wasm when running the companion target outside CI.

Fresh Shards seed Lesser Heal 2050 as a heal for a named ally. Existing Shards keep their stored
spell definitions when the Module is published, so the normal `debug_repair_after_publish` step
updates only the complete former canonical seed shape. Imported or tuned 2050 rows remain unchanged;
merging or publishing the source without that repair step does not change them.

The durable fixture now includes populated migration. Before running the complete ignored target,
build Module Wasm from core `be3fa67d0f0c24749230560544a3e8e8b577f61d` with collection
`5724de1660a2628e88320914bdd5abb0c69da517`, retain an immutable copy, and set
Expand Down
8 changes: 6 additions & 2 deletions playerbots/fixtures/actions.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
"revision": "playerbots-seeded-actions-v1",
"provenance": "core seeded templates and reserved fixture rows",
"heal_source_spell": 2050,
"heal_target": "named ally, with explicit self still admitted",
"creature_source_entry": 51000,
"companion_unrelated_creature_entry": 5090302,
"item_source": "first starter item held by the seeded role-1 bot"
},
"imported_content": null,
Expand All @@ -16,7 +18,8 @@
"provenance": "synthetic walk and obstruction arrays",
"client_geometry": null,
"blocked": "3 by 3 navigation cells, walk bytes 0, obs bytes 20, base_z 50",
"partial": "9 cells along y, one nonwalkable x sub-cell at 1210, other walk bits 1, obs bytes 255"
"partial": "9 cells along y, one nonwalkable x sub-cell at 1210, other walk bits 1, obs bytes 255",
"companion_wall": "synthetic three-cell wall at x 1205, matching nonwalkable and 4-yard obstruction columns; no extracted client geometry"
},
"spacetimedb": "2.7.1",
"rust": "1.93.0",
Expand All @@ -31,7 +34,8 @@
"spell": 5090100,
"source_spell": 2050,
"cast_time_ms": 5000,
"cost": 0
"cost": 0,
"unsupported_channel_spell": 5090104
},
"poor_range_target_x": 1400,
"quest": {
Expand Down
Loading
Loading