mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-17 16:00:26 +02:00
Compare commits
238
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9304daf2e8 | ||
|
|
8e8713681d | ||
|
|
d7099f3e40 | ||
|
|
4ba36d7305 | ||
|
|
0a62ad4610 | ||
|
|
855f083117 | ||
|
|
6f3786de91 | ||
|
|
493713b0a6 | ||
|
|
bf356fc58a | ||
|
|
6a7b919522 | ||
|
|
c1305fa94f | ||
|
|
0fc85d6c67 | ||
|
|
c0a08f395e | ||
|
|
06cb70fb58 | ||
|
|
1709698053 | ||
|
|
42dc1f546f | ||
|
|
cb72dca40f | ||
|
|
79a6482c16 | ||
|
|
bbea2a2bff | ||
|
|
bfd92ec17d | ||
|
|
57cdbd8f80 | ||
|
|
c5c5a8eaeb | ||
|
|
a3ee36b5ef | ||
|
|
30a1e0f40e | ||
|
|
327cf96d6f | ||
|
|
852ee322cc | ||
|
|
f0d4fb2608 | ||
|
|
867855d388 | ||
|
|
4af570bc08 | ||
|
|
736c217347 | ||
|
|
7a1cf79396 | ||
|
|
30edb22f36 | ||
|
|
abc1c12f1e | ||
|
|
9e7fd75f57 | ||
|
|
6754403d68 | ||
|
|
aedf5ff9bc | ||
|
|
193cbf59c7 | ||
|
|
3f02527c68 | ||
|
|
fe160e9dbe | ||
|
|
d578f88bd0 | ||
|
|
d3fc997fdc | ||
|
|
a227872ccb | ||
|
|
812ffeea33 | ||
|
|
c05864b3fc | ||
|
|
ce77db8404 | ||
|
|
39350fb81f | ||
|
|
1a15a171ac | ||
|
|
2e3841ff7d | ||
|
|
46edf53657 | ||
|
|
c3adcfe5bf | ||
|
|
3304965653 | ||
|
|
c04765d7f4 | ||
|
|
933aac6175 | ||
|
|
809408c663 | ||
|
|
601a4c1f50 | ||
|
|
133d6a5dc1 | ||
|
|
ceecb039e3 | ||
|
|
12c97ffa85 | ||
|
|
23b542601f | ||
|
|
62b630a261 | ||
|
|
a34685574f | ||
|
|
0e6327cadf | ||
|
|
eb83e9d6d1 | ||
|
|
144063871a | ||
|
|
5f82df71f0 | ||
|
|
cfdd821b45 | ||
|
|
7165d40f90 | ||
|
|
a9bbce5f7a | ||
|
|
e8e0c2215a | ||
|
|
383355381c | ||
|
|
e94906100c | ||
|
|
57add5ed71 | ||
|
|
2b0103a0ef | ||
|
|
c9ee319ab5 | ||
|
|
65d81ad1ba | ||
|
|
770f8881e0 | ||
|
|
d356c0abab | ||
|
|
38ab192749 | ||
|
|
1536c30870 | ||
|
|
827eb0fc1d | ||
|
|
458b4642b6 | ||
|
|
a482a5f5bb | ||
|
|
2af2702bfa | ||
|
|
81f321f959 | ||
|
|
7a1c5e6239 | ||
|
|
f97ff9219f | ||
|
|
a9f3ce2647 | ||
|
|
85e79a067a | ||
|
|
1cebe431d1 | ||
|
|
ec2ab73acc | ||
|
|
effeda1b7c | ||
|
|
6299503191 | ||
|
|
2f5fa771f5 | ||
|
|
c5d86c8d8b | ||
|
|
7242151017 | ||
|
|
3aa88244fc | ||
|
|
1c8e651bb1 | ||
|
|
4b8f8dde8b | ||
|
|
920b1bfea9 | ||
|
|
09f869e44c | ||
|
|
a4e1bdb80d | ||
|
|
bc45338214 | ||
|
|
ceb0260389 | ||
|
|
a663d1b100 | ||
|
|
d8034d37fd | ||
|
|
f8a39df0cd | ||
|
|
bdfdef9bd4 | ||
|
|
6057146244 | ||
|
|
f02317ca25 | ||
|
|
94b17a7913 | ||
|
|
d7fa443718 | ||
|
|
30f362ff3d | ||
|
|
4414d7606d | ||
|
|
23d14319a7 | ||
|
|
824f79aa70 | ||
|
|
25a947faac | ||
|
|
ff5b91f120 | ||
|
|
f6c2322df9 | ||
|
|
39fbaefaac | ||
|
|
bf545439b4 | ||
|
|
201f69a35a | ||
|
|
c6397cb515 | ||
|
|
80d30410c8 | ||
|
|
d1c7243cb2 | ||
|
|
fd3d62f960 | ||
|
|
5ba6c13097 | ||
|
|
96a75df218 | ||
|
|
1a732f577f | ||
|
|
66c0d33e34 | ||
|
|
b438cea479 | ||
|
|
634b4197f9 | ||
|
|
ab96597321 | ||
|
|
f0dfb58c94 | ||
|
|
9f3e8c92de | ||
|
|
f2ba71d9af | ||
|
|
0182da8172 | ||
|
|
6b77fe428a | ||
|
|
0badc451cb | ||
|
|
39a6cc9794 | ||
|
|
35b90f26fc | ||
|
|
c55e4e2b9d | ||
|
|
7cd1724fe5 | ||
|
|
bd8ec3c798 | ||
|
|
4799980e8a | ||
|
|
f8937c6179 | ||
|
|
02316c7f35 | ||
|
|
bfbac35761 | ||
|
|
8fb1647e18 | ||
|
|
943abae15a | ||
|
|
cdd0291a3f | ||
|
|
083eef0c42 | ||
|
|
c5fcfbd46a | ||
|
|
71ae1f47bc | ||
|
|
a6ca914b8a | ||
|
|
e233e1c1bb | ||
|
|
671cc9ed91 | ||
|
|
4f3ce00a8e | ||
|
|
0d548798e5 | ||
|
|
aad8719ffc | ||
|
|
e7d1ed3a67 | ||
|
|
c68db56144 | ||
|
|
f100438431 | ||
|
|
4885431af9 | ||
|
|
a3ed50c56d | ||
|
|
4adc3a87a5 | ||
|
|
b47f237dc1 | ||
|
|
a05253c181 | ||
|
|
8fce8887d5 | ||
|
|
758f07ea5f | ||
|
|
ef9b9e9b1f | ||
|
|
5ac71baf94 | ||
|
|
a17d89c6f1 | ||
|
|
f3b46607e7 | ||
|
|
b9f222222b | ||
|
|
eb76e6fb4f | ||
|
|
767613a3cf | ||
|
|
c26f2e84f8 | ||
|
|
6feea5dbaa | ||
|
|
114e4a7635 | ||
|
|
f15c1e26b0 | ||
|
|
5a23aafc3a | ||
|
|
b739e0a56c | ||
|
|
164d5aebdc | ||
|
|
fd8fc72693 | ||
|
|
8db3414dcf | ||
|
|
30709dbf0f | ||
|
|
6bfd956737 | ||
|
|
0ef2ed7dc7 | ||
|
|
045d67f861 | ||
|
|
f427d058af | ||
|
|
10644b0f07 | ||
|
|
ffa981253c | ||
|
|
2ff6516f02 | ||
|
|
84ed39e257 | ||
|
|
01298f74e9 | ||
|
|
c43e1ee461 | ||
|
|
8f3e7de9ca | ||
|
|
f3aadeab98 | ||
|
|
d8f48a2a34 | ||
|
|
21714ac086 | ||
|
|
5c867dc46e | ||
|
|
caa249457a | ||
|
|
6013deec33 | ||
|
|
1555f895a8 | ||
|
|
8fda61312f | ||
|
|
a643adea30 | ||
|
|
c0c86bda26 | ||
|
|
96a48d9daa | ||
|
|
dddaffd494 | ||
|
|
087c1f5685 | ||
|
|
51cd4d8b67 | ||
|
|
b6ef765346 | ||
|
|
cd47170f39 | ||
|
|
3c9cd59c1b | ||
|
|
c4425807c5 | ||
|
|
8994176637 | ||
|
|
ed28cb2fa1 | ||
|
|
2055d7216b | ||
|
|
ef1c625058 | ||
|
|
8fcfe9e653 | ||
|
|
391e83b11f | ||
|
|
b7874714ae | ||
|
|
5a83a7234a | ||
|
|
709bfc3a3c | ||
|
|
e59d5ca926 | ||
|
|
646da5e6f7 | ||
|
|
57591011c5 | ||
|
|
09bf46b57a | ||
|
|
ef3ec0606c | ||
|
|
d7c5c52411 | ||
|
|
baab1f8efa | ||
|
|
632bebab28 | ||
|
|
e3aea795e8 | ||
|
|
25da8a5e32 | ||
|
|
30f71413c1 | ||
|
|
9e851ed4e5 | ||
|
|
a659684885 | ||
|
|
ebd24ae1e7 |
No files matched your search
+177
-2
@@ -14,12 +14,15 @@ name: Build
|
||||
# - pushes that only change documentation do not build;
|
||||
# - Windows, whose minutes cost twice Linux's, builds only Windows;
|
||||
# - artifacts are kept for three days.
|
||||
#
|
||||
# A successful build of main is also published as a GitHub release, the
|
||||
# newest marked latest, so that
|
||||
# https://github.com/<repository>/releases/latest/download/<file> always
|
||||
# gives the latest build; the last five are kept.
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
- "docs/**"
|
||||
- "research/**"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
@@ -116,10 +119,30 @@ jobs:
|
||||
~/.gradle/wrapper
|
||||
key: gradle-${{ hashFiles('port/android/**/*.gradle*', 'port/android/gradle/wrapper/gradle-wrapper.properties') }}
|
||||
|
||||
# the app's signing key, from the ANDROID_KEYSTORE_BASE64 secret (a
|
||||
# keystore, base64) and ANDROID_KEYSTORE_PASSWORD (its password, and
|
||||
# the key's, alias halo): every build signed with it installs over the
|
||||
# one before, as the app's self-updater (Updater.java) needs. Without
|
||||
# them each build is signed with the runner's own debug key.
|
||||
- name: Signing key
|
||||
env:
|
||||
KEYSTORE: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
|
||||
run: |
|
||||
if [ -n "$KEYSTORE" ]; then
|
||||
printf '%s' "$KEYSTORE" | base64 -d > "$RUNNER_TEMP/halo.keystore"
|
||||
echo "HALO_ANDROID_KEYSTORE=$RUNNER_TEMP/halo.keystore" >> "$GITHUB_ENV"
|
||||
else
|
||||
echo "::warning::no ANDROID_KEYSTORE_BASE64 secret: the Android builds cannot update over each other"
|
||||
fi
|
||||
|
||||
- name: Debug
|
||||
env:
|
||||
HALO_ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
|
||||
run: python3 tools/ci_build.py android debug
|
||||
|
||||
- name: Release
|
||||
env:
|
||||
HALO_ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
|
||||
run: python3 tools/ci_build.py android release
|
||||
|
||||
- name: Compile cache
|
||||
@@ -191,3 +214,155 @@ jobs:
|
||||
name: halo-windows-release
|
||||
path: dist/halo-windows-release
|
||||
retention-days: 3
|
||||
|
||||
release:
|
||||
# The six builds as a release, tagged build-<run number> and marked latest
|
||||
# (every file keeps its name from release to release, for the README's
|
||||
# latest/download links); then all but the newest five build-* releases
|
||||
# go, tags and all. Only for main, and only when every platform built.
|
||||
needs: [linux, android, windows]
|
||||
if: ${{ github.ref == 'refs/heads/main' }}
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 15
|
||||
permissions:
|
||||
contents: write
|
||||
outputs:
|
||||
tag: ${{ steps.publish.outputs.tag }}
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: halo-*
|
||||
path: artifacts
|
||||
|
||||
- name: Package
|
||||
run: |
|
||||
mkdir release
|
||||
for build in artifacts/*/; do
|
||||
name="$(basename "$build")"
|
||||
(cd "$build" && zip -qr "$GITHUB_WORKSPACE/release/$name.zip" .)
|
||||
done
|
||||
ls -l release
|
||||
|
||||
- name: Publish
|
||||
id: publish
|
||||
env:
|
||||
MESSAGE: ${{ github.event.head_commit.message }}
|
||||
COMMIT_URL: ${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}
|
||||
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
run: |
|
||||
tag="build-$GITHUB_RUN_NUMBER"
|
||||
subject="$(printf '%s' "${MESSAGE:-manual run}" | head -n 1)"
|
||||
printf '%s\n\nCommit: %s\nBuild: %s\n\nThe release builds are for playing; the debug builds stop at the first failed assertion and log it.\n' \
|
||||
"$subject" "$COMMIT_URL" "$RUN_URL" > notes.md
|
||||
gh release create "$tag" release/*.zip --target "$GITHUB_SHA" --latest \
|
||||
--title "Build $GITHUB_RUN_NUMBER (${GITHUB_SHA:0:7})" --notes-file notes.md
|
||||
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Keep the last five
|
||||
run: |
|
||||
gh release list --limit 100 --json tagName,createdAt \
|
||||
--jq '[.[] | select(.tagName | startswith("build-"))] | sort_by(.createdAt) | reverse | .[5:] | .[].tagName' |
|
||||
while read -r tag; do
|
||||
gh release delete "$tag" --cleanup-tag --yes
|
||||
done
|
||||
|
||||
notify:
|
||||
# A Discord embed for the run, to the DISCORD_WEBHOOK secret (nothing
|
||||
# without it): green when every platform built, red when one did not,
|
||||
# with each platform's result, this run's release (main only), and links
|
||||
# to the latest release's builds.
|
||||
needs: [linux, android, windows, release]
|
||||
if: ${{ !cancelled() }}
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Post to Discord
|
||||
env:
|
||||
WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
LINUX: ${{ needs.linux.result }}
|
||||
ANDROID: ${{ needs.android.result }}
|
||||
WINDOWS: ${{ needs.windows.result }}
|
||||
RELEASE_TAG: ${{ needs.release.outputs.tag }}
|
||||
SERVER: ${{ github.server_url }}
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
BRANCH: ${{ github.ref_name }}
|
||||
SHA: ${{ github.sha }}
|
||||
ACTOR: ${{ github.actor }}
|
||||
MESSAGE: ${{ github.event.head_commit.message }}
|
||||
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
COMMIT_URL: ${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}
|
||||
run: |
|
||||
if [ -z "$WEBHOOK" ]; then
|
||||
echo "no DISCORD_WEBHOOK secret: nothing to post"
|
||||
exit 0
|
||||
fi
|
||||
status() {
|
||||
case "$1" in
|
||||
success) echo "✅ Built" ;;
|
||||
failure) echo "❌ Failed" ;;
|
||||
cancelled) echo "⏹️ Cancelled" ;;
|
||||
*) echo "➖ Skipped" ;;
|
||||
esac
|
||||
}
|
||||
if [ "$LINUX" = success ] && [ "$ANDROID" = success ] && [ "$WINDOWS" = success ]; then
|
||||
title="Build succeeded"; color=5763719
|
||||
else
|
||||
title="Build failed"; color=15548997
|
||||
fi
|
||||
latest="$SERVER/$REPOSITORY/releases/latest"
|
||||
downloads="[Linux]($latest/download/halo-linux-release.zip) · [Windows]($latest/download/halo-windows-release.zip) · [Android]($latest/download/halo-android-release.zip) ([all builds]($latest))"
|
||||
if [ -n "$RELEASE_TAG" ]; then
|
||||
release="[$RELEASE_TAG]($SERVER/$REPOSITORY/releases/tag/$RELEASE_TAG)"
|
||||
else
|
||||
release="None (only a successful build of main makes one)"
|
||||
fi
|
||||
subject="$(printf '%s' "${MESSAGE:-manual run}" | head -n 1 | cut -c1-200)"
|
||||
jq -n \
|
||||
--arg title "$title" --argjson color "$color" --arg url "$RUN_URL" \
|
||||
--arg description "[\`${SHA:0:7}\`]($COMMIT_URL) $subject — $ACTOR ($BRANCH)" \
|
||||
--arg release "$release" --arg downloads "$downloads" \
|
||||
--arg linux "$(status "$LINUX")" --arg windows "$(status "$WINDOWS")" --arg android "$(status "$ANDROID")" \
|
||||
--arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
||||
'{embeds: [{
|
||||
title: $title, url: $url, color: $color, description: $description, timestamp: $timestamp,
|
||||
fields: [
|
||||
{name: "Linux", value: $linux, inline: true},
|
||||
{name: "Windows", value: $windows, inline: true},
|
||||
{name: "Android", value: $android, inline: true},
|
||||
{name: "Release", value: $release},
|
||||
{name: "Latest release builds", value: $downloads}
|
||||
]
|
||||
}]}' > payload.json
|
||||
# Discord rate limits webhooks (HTTP 429, with how many seconds to
|
||||
# wait in retry_after): wait and try again, a few times. A post
|
||||
# still limited, or a network or Discord error, is a warning rather
|
||||
# than a failed run; any other answer (a deleted webhook) fails. (At
|
||||
# most 5 tries of 15 seconds and 4 waits of 30: inside the job's 5
|
||||
# minutes.)
|
||||
for attempt in 1 2 3 4 5; do
|
||||
code=$(curl -sS --max-time 15 -o response.json -w '%{http_code}' \
|
||||
-H "Content-Type: application/json" -d @payload.json "$WEBHOOK") || code=000
|
||||
case "$code" in
|
||||
2??)
|
||||
exit 0
|
||||
;;
|
||||
429)
|
||||
wait=$(jq -r '.retry_after // 5' response.json 2>/dev/null || echo 5)
|
||||
wait=$(awk -v w="$wait" 'BEGIN { w += 0; if (w < 1) w = 1; if (w > 30) w = 30; printf "%d", w + 0.999 }')
|
||||
echo "Discord is rate limiting the webhook; trying again in ${wait}s (attempt $attempt of 5)"
|
||||
;;
|
||||
000|5??)
|
||||
wait=5
|
||||
echo "Discord answered HTTP $code; trying again in ${wait}s (attempt $attempt of 5)"
|
||||
;;
|
||||
*)
|
||||
echo "::error::Discord answered HTTP $code: $(cat response.json 2>/dev/null)"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
[ "$attempt" -lt 5 ] && sleep "$wait"
|
||||
done
|
||||
echo "::warning::The Discord post did not go through after 5 attempts (HTTP $code)"
|
||||
+4
-17
@@ -9,36 +9,23 @@ __pycache__
|
||||
|
||||
# Build files
|
||||
build/
|
||||
projects/
|
||||
.ninja_*
|
||||
build.ninja
|
||||
*.vcxproj*
|
||||
*.sln*
|
||||
|
||||
# decompctx output
|
||||
ctx.*
|
||||
*.ctx
|
||||
|
||||
# Generated configs
|
||||
objdiff.json
|
||||
compile_commands.json
|
||||
|
||||
# Miscellaneous
|
||||
# The January build and the Xbox SDK (tools/xdk_headers.py reads the
|
||||
# build's PDB); never commit
|
||||
*.exe
|
||||
*.pdb
|
||||
*.idb
|
||||
*.i64
|
||||
*.id0
|
||||
*.id1
|
||||
*.id2
|
||||
*.nam
|
||||
*.til
|
||||
*.bndb
|
||||
xbox/
|
||||
!source/**/xbox/
|
||||
|
||||
# Locally extracted proprietary game data (never commit)
|
||||
assets/
|
||||
# (but the high-res assets, drawn for the port: tools/hud_assets.py)
|
||||
!port/assets/
|
||||
original/
|
||||
|
||||
# CI build outputs (tools/ci_build.py)
|
||||
|
||||
@@ -1,77 +1,140 @@
|
||||
Halo 1 xbox decomp, ported to Linux, Windows and Android
|
||||
=============
|
||||
# Halo: Combat Evolved for Linux, Windows and Android
|
||||
|
||||
This is a port of the decompilation of Halo: Combat Evolved build 2342 (`cachebeta.exe`, sha256 `4cc87b45f721270392a96f1674ed2b5cd4a7bb4355faeab4531d1cf1884d9520`) to Linux, Windows and Android.
|
||||
[](https://discord.gg/9gqcHyr5km)
|
||||
|
||||
<img width="1289" height="995" alt="image" src="https://github.com/user-attachments/assets/0d3ad50f-f8b8-46cf-aef8-e3661da2a7d7" />
|
||||
This project is a port of the Halo: Combat Evolved decompilation to Linux,
|
||||
Windows and Android. The decompilation is of the Xbox build 2342
|
||||
(`cachebeta.exe`, SHA-256
|
||||
`4cc87b45f721270392a96f1674ed2b5cd4a7bb4355faeab4531d1cf1884d9520`).
|
||||
|
||||
This is based on [bnunu](https://github.com/bnunu/halo)'s decompilation project, which itself is a fork of [punpckhdq/halo](https://github.com/punpckhdq/halo).
|
||||
<img width="1289" height="995" alt="The game on Linux" src="https://github.com/user-attachments/assets/0d3ad50f-f8b8-46cf-aef8-e3661da2a7d7" />
|
||||
|
||||
## Agent quick references
|
||||
The port starts from the decompilation of [bnunu/halo-1](https://github.com/bnunu/halo-1).
|
||||
That project is a fork of [punpckhdq/halo](https://github.com/punpckhdq/halo).
|
||||
|
||||
- [Current campaign house rules and batch/treemap cadence](docs/campaign_house_rules.md)
|
||||
- [Common constants, types, float patterns, tag IDs, and flag conventions](docs/common_constants.md)
|
||||
- [Shared assertion macros and byte-matching examples](docs/assertions.md)
|
||||
- [Supplied CE source maps, recovered names, and next reconstruction packets](docs/user_source_reconstruction_map_20260906.md)
|
||||
- [Matching methodology and source-credibility rules](docs/matching_methodology.md)
|
||||
## Download
|
||||
|
||||
## Build instructions
|
||||
GitHub Actions builds the game for each commit. These links download the
|
||||
builds of the latest release:
|
||||
|
||||
You need Python and [ninja-build](https://ninja-build.org/) on your PATH; run `configure.py` from the repository root, then `ninja` with the target below (plain `ninja` builds the one for the computer you are on). No part of the Xbox SDK is needed: the SDK declarations the game uses are in [port/include/xdk](port/include/xdk/README.md).
|
||||
| Platform | Release | Debug |
|
||||
| --- | --- | --- |
|
||||
| Linux | [halo-linux-release.zip](https://github.com/cybersecurity/halo-ce-universal/releases/latest/download/halo-linux-release.zip) | [halo-linux-debug.zip](https://github.com/cybersecurity/halo-ce-universal/releases/latest/download/halo-linux-debug.zip) |
|
||||
| Windows | [halo-windows-release.zip](https://github.com/cybersecurity/halo-ce-universal/releases/latest/download/halo-windows-release.zip) | [halo-windows-debug.zip](https://github.com/cybersecurity/halo-ce-universal/releases/latest/download/halo-windows-debug.zip) |
|
||||
| Android | [halo-android-release.zip](https://github.com/cybersecurity/halo-ce-universal/releases/latest/download/halo-android-release.zip) | [halo-android-debug.zip](https://github.com/cybersecurity/halo-ce-universal/releases/latest/download/halo-android-debug.zip) |
|
||||
|
||||
Every pushed commit is built by GitHub Actions ([.github/workflows/build.yml](.github/workflows/build.yml)): debug and release builds for Linux, Windows and Android, made by `tools/ci_build.py` (which also works locally, e.g. `python tools/ci_build.py linux release`) and kept as artifacts for three days.
|
||||
Use the release build to play. The debug build stops at the first failed
|
||||
assertion and writes it to the log. Use the debug build to find and report
|
||||
problems.
|
||||
|
||||
### Native Linux build
|
||||
The game updates itself. At start-up it looks for a newer release, and asks
|
||||
if you want to install it. Refer to "Updates" in
|
||||
[port/linux/README.md](port/linux/README.md#updates).
|
||||
|
||||
`ninja linux` compiles the game with clang into a native 32-bit Linux executable, `build/linux/halo`. It needs clang, 32-bit glibc development files and 32-bit SDL3. It renders with OpenGL, plays sound through SDL3 audio, and takes keyboard, mouse and gamepad input. Put the PAL game data (build 01.01.14.2342) under `assets/` so that `assets/maps` exists, then run `build/linux/halo`. See [port/linux/README.md](port/linux/README.md) for controls and settings.
|
||||
Each build of the `main` branch that passes on all three platforms is a new
|
||||
release. The [Releases](https://github.com/cybersecurity/halo-ce-universal/releases)
|
||||
page keeps the last five releases. If the latest build has a problem, get
|
||||
an older build from that page.
|
||||
|
||||
### Debug and release
|
||||
## Game data
|
||||
|
||||
The native builds (Linux, Windows, Android) are debug builds by default: like the build the decompilation reproduces, they stop at the first failed assertion and log it. `python configure.py --release` configures release builds instead, which, like the retail game, do not check assertions. The byte-matching build is unaffected.
|
||||
The port does not include the game data. Download an Xbox disc image
|
||||
(`.xiso` or `.iso`) of Halo: Combat Evolved. All versions of the game
|
||||
operate. The maps of the European (PAL) version were made for a slower
|
||||
console. The port changes them to play as the North American (NTSC) maps do,
|
||||
so players of the two versions can play together.
|
||||
|
||||
### Optimisation
|
||||
1. Start the game.
|
||||
2. At the first start, the game asks for the disc image. Select it.
|
||||
3. The game extracts the `maps/` folder. Then the game starts.
|
||||
|
||||
The Linux and Windows builds are optimised for the processor of the computer that builds them (`-march=native`), and may not start on another. `python configure.py --portable` targets the x86-64 baseline instead (SSE2, which every 64-bit x86 processor has): use it for builds you share.
|
||||
On Linux and Windows, the game puts `maps/` next to the executable. On
|
||||
Android, copy the disc image to the phone first. The app puts `maps/` in its
|
||||
data folder. Refer to [port/android/README.md](port/android/README.md).
|
||||
|
||||
They also use full link-time optimisation by default, which makes the final link take a minute or so; `--lto=thin` links in parallel and incrementally, `--lto=off` not at all.
|
||||
## Platforms
|
||||
|
||||
They are also optimised with profiles of the game at play, recorded by an instrumented build playing the main menu and the opening minute of every campaign level by itself: `pgo/halo_linux.profdata` for Linux (and Android, whose code is almost the same) and `pgo/halo_windows.profdata` for Windows. The profiles need clang 22 or later; with an older clang, and with `--pgo=off`, the builds do without. A profile stays useful as the code changes (functions it does not know simply go without). To record a new one, delete it and configure with `--pgo=train`: `ninja linux` or `ninja windows` then builds the instrumented game and plays the levels (about fifteen minutes, in a window, silently; it needs the game data in `assets/`) before the real build. Over ssh, Windows plays them on the logged-in user's desktop, through a scheduled task. `--pgo-profile <file>` uses another profile.
|
||||
Each platform has its own instructions:
|
||||
|
||||
With Mesa drivers the Linux build makes its GL calls through Mesa's GL thread (`mesa_glthread`), which takes them off the game's thread.
|
||||
| Platform | Instructions |
|
||||
| --- | --- |
|
||||
| Linux (32-bit x86 executable, OpenGL 4.5, SDL3) | [port/linux/README.md](port/linux/README.md) |
|
||||
| Windows (32-bit x86 executable, OpenGL 4.5, SDL3) | [port/windows/README.md](port/windows/README.md) |
|
||||
| Android (arm64 app, OpenGL ES 3, SDL3) | [port/android/README.md](port/android/README.md) |
|
||||
|
||||
Frames per second at the opening of a30, uncapped (`vsync = false` in `config.toml`, or `HALO_NO_VSYNC=1`), about 510 draws per frame; each row adds one change to the one above (Linux: a laptop with an Intel Core i7-1355U and Iris Xe graphics, median of three runs; Android: a Pixel 9 Pro XL, Tensor G4, median of three runs):
|
||||
The Linux README also gives the controls, the settings and the multiplayer
|
||||
functions. These are almost the same on all platforms.
|
||||
|
||||
| Change | Linux | Android |
|
||||
| --- | ---: | ---: |
|
||||
| Original | 103 | 132 |
|
||||
| GL state set only when it changes | 139 | 156 |
|
||||
| Vertex and index buffers from a GL copy of the Xbox memory | 171 | 193 |
|
||||
| Full link-time optimisation | 189 | not applicable |
|
||||
| Profile-guided optimisation | 201 | 197 |
|
||||
| `-march=native` (`--portable`, x86-64: 212; Android: `-mcpu=cortex-x3`, not used) | 224 | 191 |
|
||||
| Mesa's GL thread | 257 | not applicable |
|
||||
| Sound obstruction tested once per game tick, cheaper per-draw bookkeeping | 303 | 220 |
|
||||
## Multiplayer
|
||||
|
||||
Android has no equivalent of `-march=native`: the build runs on any 64-bit phone, and compiling for the Pixel's big cores made it slower there anyway, so its last row builds on the profile-guided one. On the laptop the game's own thread no longer sets the frame rate: it spends about as long waiting for the GL and driver threads and the GPU (which the laptop's power management keeps at a low clock for this load) as they spend waiting for it. The same holds in heavier scenes such as b30, at about 190.
|
||||
The game can play system link games on a local network and on the internet:
|
||||
|
||||
Unity ("jumbo") builds, which compile many files as one, would give the compiler nothing full link-time optimisation does not already see, and the decompiled sources declare too many conflicting local types for it anyway. `-O3` and profile-driven function splitting measured no faster than `-O2`.
|
||||
- A system link game can have up to 128 players on up to 128 machines.
|
||||
- Linux, Windows and Android machines can play in the same game.
|
||||
- An invite link lets a machine join a game on the internet. No server of
|
||||
this project is necessary.
|
||||
- The netcode is new. Each machine moves its own player at once,
|
||||
and the host makes the decisions for the game. Refer to
|
||||
[port/linux/NETCODE.md](port/linux/NETCODE.md).
|
||||
|
||||
### Frame rate
|
||||
## Build the game
|
||||
|
||||
The native builds draw a frame at every refresh of the display (60, 90, 120, 240 Hz, ...), paced by vsync, while the game still simulates at 30 Hz as on the Xbox: each frame blends the last two ticks. To see the frame rate, open the developer console (the \` key) and enter `display_framerate true`; the frames per second, averaged over half a second, appear at the bottom right of the screen. `interpolation = false` in `config.toml` (written next to the executable, or in the data folder on Android, on the first run) restores the original 30 frames per second. See [port/linux/README.md](port/linux/README.md#frame-rate).
|
||||
You do not need the Xbox SDK. The port supplies the SDK declarations that
|
||||
the game uses. Refer to [port/include/xdk](port/include/xdk/README.md).
|
||||
|
||||
### Native Windows build
|
||||
To build the game:
|
||||
|
||||
`ninja windows`, run on Windows, compiles the game with clang into a native 32-bit Windows executable, `build/windows/halo.exe` (with `SDL3.dll`), sharing the Linux build's platform layer. It needs LLVM, Python and ninja, plus Visual Studio's x86 C++ libraries and a Windows SDK. Put the game data under `assets/` as for Linux. See [port/windows/README.md](port/windows/README.md).
|
||||
1. Install Python and [ninja](https://ninja-build.org/).
|
||||
2. Install the tools for your platform. Refer to the README for the
|
||||
platform.
|
||||
3. In the root folder of the repository, enter `python configure.py`.
|
||||
4. Enter `ninja` with the target for the platform:
|
||||
|
||||
### Android build
|
||||
| Target | Result |
|
||||
| --- | --- |
|
||||
| `ninja linux` | `build/linux/halo` |
|
||||
| `ninja windows` (on Windows) | `build/windows/halo.exe` and `SDL3.dll` |
|
||||
| `ninja android_apk` | `port/android/app/build/outputs/apk/debug/app-debug.apk` |
|
||||
|
||||
`ninja android_apk` builds an arm64 Android app (`port/android/app/build/outputs/apk/debug/app-debug.apk`) that runs the game natively on 64-bit ARM phones, with OpenGL ES 3 rendering at the device's aspect ratio, SDL3 audio and game controller support (including a PS5 DualSense over Bluetooth). It needs the Android NDK and a clang with the `arm64_32` target in addition to the Linux build's requirements. The game data goes in the app's storage (the app offers to import it). See [port/android/README.md](port/android/README.md).
|
||||
If you enter `ninja` without a target, ninja builds the game for the
|
||||
computer that you use.
|
||||
|
||||
### Matching build
|
||||
`tools/ci_build.py` makes the same builds as GitHub Actions. For example,
|
||||
enter `python tools/ci_build.py linux release`.
|
||||
|
||||
This fork builds only the native ports. The upstream project's byte-matching build, which compiles the game with the Xbox SDK's own compiler and compares it with `cachebeta.exe`, needs the August 2001 Xbox SDK, which cannot be redistributed, so `configure.py` no longer writes it. Its sources, configuration and `#ifdef`s are kept as they are, so that upstream's matching work still merges; `SolutionConfig.matching` in `tools/project_x86.py` turns it back on, for a checkout with the SDK's `XDK/xbox` folder extracted to `xbox/` and `cachebeta.exe` in the repository root. See [port/linux/README.md](port/linux/README.md#the-matching-build-on-a-linux-host) for running it on Linux.
|
||||
### Build options
|
||||
|
||||
## Where's all the type information?
|
||||
Give these options to `configure.py`:
|
||||
|
||||
We use debug symbols from later Halo games to help map structures, enums, type definitions, function signatures and some variable names. You should obtain a copy of the Halo CEA beta and run it through [pdb-decompiler](https://github.com/camden-smallwood/pdb-decompiler) to obtain debug info for yourself. Note that CEA is based off of Halo PC and has its own modifications which make it not 100% accurate to the original Xbox title.
|
||||
| Option | Result |
|
||||
| --- | --- |
|
||||
| (none) | A debug build. A failed assertion stops the game. |
|
||||
| `--release` | A release build. The game does not examine assertions, as in the retail game. |
|
||||
| `--portable` | The Linux and Windows builds operate on all x86-64 processors. Use this option for builds that you give to other persons. |
|
||||
| `--lto=thin`, `--lto=off` | Less link-time optimization. The link is faster. |
|
||||
| `--pgo=off` | No profile-guided optimization. |
|
||||
| `--pgo=train` | Records a new optimization profile. Refer to "Optimization profiles". |
|
||||
|
||||
Without `--portable`, the Linux and Windows builds use all the instructions
|
||||
of the processor that builds them (`-march=native`). Such a build does not
|
||||
always start on a different computer.
|
||||
|
||||
### Optimization profiles
|
||||
|
||||
The builds use profiles of the game to optimize the code:
|
||||
|
||||
- `pgo/halo_linux.profdata` for Linux and Android.
|
||||
- `pgo/halo_windows.profdata` for Windows.
|
||||
|
||||
The profiles need clang 22 or later. With an older clang, the builds do not
|
||||
use the profiles.
|
||||
|
||||
To record a new profile:
|
||||
|
||||
1. Delete the profile.
|
||||
2. Enter `python configure.py --pgo=train`.
|
||||
3. Enter `ninja linux` or `ninja windows`.
|
||||
|
||||
The build then plays the main menu and the first minute of each campaign
|
||||
level. This procedure continues for approximately 15 minutes. The game
|
||||
data must be in `assets/`.
|
||||
-1304
File diff suppressed because it is too large.
Load diff
-22457
File diff suppressed because it is too large.
Load diff
@@ -1,45 +0,0 @@
|
||||
{
|
||||
"version": 1,
|
||||
"entries": [
|
||||
{
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox_profile",
|
||||
"class": "source-layout-incomplete",
|
||||
"symbol": "_rasterizer_profile_globals",
|
||||
"reason": "All 16 target functions and all 2234 target data bytes are exact. The three stock SDK select-any tables (D3DTEXTUREDIRECTENCODE 16 bytes, D3DSIMPLERENDERSTATEENCODE 328, D3DPRIMITIVETOVERTEXCOUNT 88) come from D3D8.h's unconditional extern const selectany definitions, which January's TU included (its object imports _D3DDevice_InsertCallback@12 and QueryPerformance*). Each copy is byte-identical to January's selected provider and passes the selected-provider pair links in both orders, the standard under which collision_debug and the other Matching emitters carry the same tables. Canonical's dynavobgeom reconciliation (641e1466, docs/object_matching_logs/claude_fifty_objects_canonical_reconciliation.md) still leaves stock SDK-table coalescing open pending a uniform owner policy audit, so this object inherits that decision. Whole-object admission also fails source authenticity. The private state is written as four invented file-static aggregates (rasterizer_profile_globals, rasterizer_profile_elapsed_state, rasterizer_profile_frame_state, rasterizer_profile_state). Their pad02/pad06/pad12/pad16 members only spell out VC7's per-static 4-byte alignment padding, and reserved06[6] hides one unattested 4-byte object at .bss +0x45c. Loose file statics reproduce every code byte and every other data offset, and the later /Od build places elapsed_times before callback_start_times, contradicting the elapsed_state member order. The rasterizer_profile_check NONE branch reproduces January's format/varargs defect (%s consumes the NONE profile value), which awaits the owner's original-bug ruling. Three load-bearing volatile qualifiers have no first-party attestation. The TU also still declares global_window_parameters with a consumer-local extern: moving it to the owner header rasterizer_xbox_internal.h keeps every exact section byte-identical but declares the name earlier in rasterizer_xbox_models, which moves the residual __rasterizer_model_draw by one instruction.",
|
||||
"evidence": "research/fifty_objects_20260925/w/review3_rasterizer_xbox_profile/REVIEW.md",
|
||||
"reopen": "Recover the genuine January private state shape: replace the invented aggregates with authentic separate file statics, or first-party-attested structures, without fabricated pad/reserved members. Identify the unreferenced 4-byte January object at .bss +0x45c from first-party evidence rather than a filler. Obtain the owner's rulings on the BUG-marked NONE-branch varargs defect and the three volatile qualifiers. Any new private names need the owner's descriptive-name policy (as for the held rasterizer_xbox .bss split). Preserve all 16 target functions and all data sections, land the pinned 132-byte .data entry only with the Matching flip, move the window extern to its owner header with a full consumer sweep (re-baselining the rasterizer_xbox_models __rasterizer_model_draw park it perturbs), and apply the owner's uniform stock SDK-table decision from the open dynavobgeom reconciliation."
|
||||
},
|
||||
{
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox_dynavobgeom",
|
||||
"class": "candidate-only-comdat-owner",
|
||||
"symbol": "_D3DSIMPLERENDERSTATEENCODE",
|
||||
"reason": "All 17 January code functions and all 31 January-owned sections/symbols match after replacing local debug, window and pixel-shader views with genuine owner types. Nine D3DINLINE wrappers have January's file-static storage. The two surplus color-conversion helpers are byte-identical to January's selected providers, and all 17 surplus symbols pass selected-provider links in both orders. The global_window_parameters extern still lives in consumer C files, with incompatible partial views in other consumers rather than a common owner declaration. Three stock SDK tables and other candidate-only constants/literals remain absent from January's split; the selected-provider test ignores unrelated unresolved symbols. A complete ordinary final-link ownership proof has not been established, so exact function credit does not imply Matching.",
|
||||
"evidence": "docs/object_matching_logs/rasterizer_xbox_dynavobgeom_owner_layout_reconciliation.md",
|
||||
"reopen": "Move global_window_parameters to its authentic owner declaration and reconcile the partial consumer views with a full regression sweep. Establish selected ownership/coalescing of candidate-only SDK tables and helper data through a complete compatible ordinary link or equally decisive January source/link evidence, without losing target exactness. Do not suppress genuine header emissions, alter selection metadata, force-inline, hand-copy helpers or count candidate-only bytes as January-owned."
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/hud_draw",
|
||||
"class": "candidate-only-comdat-owner",
|
||||
"symbol": "_fast_ftol",
|
||||
"reason": "The exact flash-duration leaf uses the authentic shared conversion helper and naturally emits an additional unreferenced select-any32-byte fast_ftol copy absent from January HUD Draw. January's identical selected Actor Combat copy is no-duplicates; its ordinary XDK duplicate-owner failure is already documented. The two newly exact drawing helpers receive valid target-function credit, but no whole-object or linked-coalescing claim follows.",
|
||||
"evidence": "docs/object_matching_logs/hud_draw_obj_two_exact_leaves_integration_20260904.md#complete-owner-boundary",
|
||||
"reopen": "Require authentic source topology or an ordinary base/base link with an authenticated compatible canonical selected helper before clearing this veto. Do not force inline, manually expand math, alter target/COMDAT metadata, invent a discard pass, or credit candidate-only helper bytes. All remaining HUD Draw functions/data/linkage/source checks must independently pass before whole-object Matching."
|
||||
},
|
||||
{
|
||||
"unit": "source/effects/decals",
|
||||
"class": "candidate-only-comdat-owner",
|
||||
"symbol": "_vector_from_points2d",
|
||||
"reason": "The exact typed decal_projection_create body naturally inlines vector_from_points2d as January requires, but VC7 also emits an unreferenced select-any helper body absent from the January Decals split. January's selected Action Obey copy is no-duplicates. The exact target function receives valid credit; the surplus helper receives none and blocks whole-object Matching.",
|
||||
"evidence": "docs/object_matching_logs/decals_obj_color_projection_packet_20260912.md#inline-helper-ownership-boundary",
|
||||
"reopen": "Remove only when authentic source topology or an ordinary compatible canonical link preserves decal_projection_create while preventing or safely coalescing the extra helper. Do not force inline, manually expand the helper for code shaping, alter COMDAT metadata, or count the candidate-only bytes."
|
||||
},
|
||||
{
|
||||
"unit": "source/effects/decals",
|
||||
"class": "candidate-only-comdat-owner",
|
||||
"symbol": "_cross_product2d",
|
||||
"reason": "The exact typed decal_projection_create body naturally inlines cross_product2d as January requires, but VC7 also emits an unreferenced select-any helper body absent from the January Decals split. January's selected Actor Combat copy is no-duplicates. The exact target function receives valid credit; the surplus helper receives none and blocks whole-object Matching.",
|
||||
"evidence": "docs/object_matching_logs/decals_obj_color_projection_packet_20260912.md#inline-helper-ownership-boundary",
|
||||
"reopen": "Remove only when authentic source topology or an ordinary compatible canonical link preserves decal_projection_create while preventing or safely coalescing the extra helper. Do not force inline, manually expand the helper for code shaping, alter COMDAT metadata, or count the candidate-only bytes."
|
||||
}
|
||||
]
|
||||
}
|
||||
-1162
File diff suppressed because it is too large.
Load diff
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"debug_sections": [
|
||||
{
|
||||
"after_fingerprint_sha256": "8e07b48ebedfa52de730be35f0b56d2fadb9b72e51a1edd029e20b5bb5cddc23",
|
||||
"before_fingerprint_sha256": "92288b56cfbca8760857b38d5fb34cdfe3b56c092891ebfa6c00dc9cfc68b395",
|
||||
"recipe": "xdk-stock-d3dinline",
|
||||
"section": ".debug$F|anonymous=2",
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox_plasma_energy"
|
||||
},
|
||||
{
|
||||
"after_fingerprint_sha256": "5b79f3d7f6d7cd9eca0a4324f66baf87dff523b69e917689707607178a0b48ab",
|
||||
"before_fingerprint_sha256": "fd054221f7d9970be62ba370272c65e7c78a8a116110be3a5796fb06a8127ece",
|
||||
"recipe": "xdk-stock-d3dinline",
|
||||
"section": ".debug$S|anonymous=0",
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox_plasma_energy"
|
||||
}
|
||||
],
|
||||
"functions": [],
|
||||
"schema_version": 1
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
{
|
||||
"debug_sections": [
|
||||
{
|
||||
"after_fingerprint_sha256": "8e07b48ebedfa52de730be35f0b56d2fadb9b72e51a1edd029e20b5bb5cddc23",
|
||||
"before_fingerprint_sha256": "92288b56cfbca8760857b38d5fb34cdfe3b56c092891ebfa6c00dc9cfc68b395",
|
||||
"recipe": "xdk-stock-d3dinline",
|
||||
"section": ".debug$F|anonymous=2",
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox_text"
|
||||
}
|
||||
],
|
||||
"functions": [
|
||||
{
|
||||
"after_comdat_selection": 2,
|
||||
"after_fingerprint_sha256": "458fb5bd5e078ea76d95e47dd9632bb3bb0b3a25c8aa64efba41fd359a99b2cf",
|
||||
"before_comdat_selection": 1,
|
||||
"before_fingerprint_sha256": "9ff19872aa908361445bece0a21cab0ca4c93f68cb7bad1bcc70e77f0de6c6c8",
|
||||
"function": "_D3DDevice_SetRenderState",
|
||||
"recipe": "xdk-stock-d3dinline",
|
||||
"source_recipe": "stock XDK D3DINLINE (static __forceinline)",
|
||||
"target_evidence_sha256": "ef767bb47681ea399daf6f8720f056e523790d105bcea1f634d71c3e3611d192",
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox_text"
|
||||
},
|
||||
{
|
||||
"after_comdat_selection": 2,
|
||||
"after_fingerprint_sha256": "459f5d33ded34255e79f255c42a193c74066bdad08fc9116b2dd82eaf16ee094",
|
||||
"before_comdat_selection": 1,
|
||||
"before_fingerprint_sha256": "142d63782a1e9e3a41a5f722084b8681b1bf765912c4dd91784299a280112204",
|
||||
"function": "_D3DDevice_SetTextureStageState",
|
||||
"recipe": "xdk-stock-d3dinline",
|
||||
"source_recipe": "stock XDK D3DINLINE (static __forceinline)",
|
||||
"target_evidence_sha256": "ef19cb2f99aa7c1ad0f06f57c44a2dbace4b75ba6c779e68a1885e832d50d6c4",
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox_text"
|
||||
},
|
||||
{
|
||||
"after_comdat_selection": 2,
|
||||
"after_fingerprint_sha256": "5382805b884f0d40e945936f88f42d2b3c9f0c5ca0f83098312bc5a8444c3d66",
|
||||
"before_comdat_selection": 1,
|
||||
"before_fingerprint_sha256": "8f5385e5727b96b51ea06b98ff74fc9ba2f57802f0118f6f759e32ed3bb60797",
|
||||
"function": "_IDirect3DDevice8_Begin@8",
|
||||
"recipe": "xdk-stock-d3dinline",
|
||||
"source_recipe": "stock XDK D3DINLINE (static __forceinline)",
|
||||
"target_evidence_sha256": "f9f8776473104153fbb44b071659641050b0ef17ffde33740e053f1d31598d86",
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox_text"
|
||||
},
|
||||
{
|
||||
"after_comdat_selection": 2,
|
||||
"after_fingerprint_sha256": "a6c5208bf1949404ef5f4340bb14eff5ffab46a37c3aa041c2d5e4523b1dd8c2",
|
||||
"before_comdat_selection": 1,
|
||||
"before_fingerprint_sha256": "7916c2492802dcf917429ec316aefe67fbd8c96ef60bad99e12e26c38271342a",
|
||||
"function": "_IDirect3DDevice8_End@4",
|
||||
"recipe": "xdk-stock-d3dinline",
|
||||
"source_recipe": "stock XDK D3DINLINE (static __forceinline)",
|
||||
"target_evidence_sha256": "2acf41df227cc5ab56a634bc22b9a1af2f3594aa640b8a26e2126783c6802ed2",
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox_text"
|
||||
},
|
||||
{
|
||||
"after_comdat_selection": 2,
|
||||
"after_fingerprint_sha256": "09a181160ca4a0cec88563ed68f170bb7562d98e07cae82eb6ede383067e867c",
|
||||
"before_comdat_selection": 1,
|
||||
"before_fingerprint_sha256": "41c0a05e408be665a1bb43ea64bc56c1dbca0c5ef460f81b4248f6d02a2999d3",
|
||||
"function": "_IDirect3DDevice8_SetTextureStageState@16",
|
||||
"recipe": "xdk-stock-d3dinline",
|
||||
"source_recipe": "stock XDK D3DINLINE (static __forceinline)",
|
||||
"target_evidence_sha256": "b53ab8eb325c14f08df0e98df7b272a3dceb09921ed0d1dbeea49b69e07557f2",
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox_text"
|
||||
},
|
||||
{
|
||||
"after_comdat_selection": 2,
|
||||
"after_fingerprint_sha256": "13ff5c4aa2773bc0df32f62fce0afe58261ebabf2b2ca76426ef01a613fa7bf0",
|
||||
"before_comdat_selection": 1,
|
||||
"before_fingerprint_sha256": "7bb9a9967e3ddbbadfd0667b85c8f52ee06137a1f0b0cd4a0e45a4e1247d1815",
|
||||
"function": "_IDirect3DDevice8_SetVertexData2f@16",
|
||||
"recipe": "xdk-stock-d3dinline",
|
||||
"source_recipe": "stock XDK D3DINLINE (static __forceinline)",
|
||||
"target_evidence_sha256": "1303752bb188cf6b5a00adb8c2c49092f22408c2c38203e8daddf5b61aa61153",
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox_text"
|
||||
},
|
||||
{
|
||||
"after_comdat_selection": 2,
|
||||
"after_fingerprint_sha256": "78b5829871e22251b4e266bd81caa2eda338a6e93f43c2a592c93eaad8808e6b",
|
||||
"before_comdat_selection": 1,
|
||||
"before_fingerprint_sha256": "464ecff7dc1e2d1a1c18d02c467dcbe893baedfebfa42920922583cde75b9331",
|
||||
"function": "_IDirect3DDevice8_SetVertexDataColor@12",
|
||||
"recipe": "xdk-stock-d3dinline",
|
||||
"source_recipe": "stock XDK D3DINLINE (static __forceinline)",
|
||||
"target_evidence_sha256": "e4a0591ba36b4fdad4a24f1009fed7b141c8acf919c8a4bca421435760c2e38a",
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox_text"
|
||||
},
|
||||
{
|
||||
"after_comdat_selection": 2,
|
||||
"after_fingerprint_sha256": "c936826f1cdc47b8e52662c867164d8fa9063b86bd7050db06a3992a0414dba7",
|
||||
"before_comdat_selection": 1,
|
||||
"before_fingerprint_sha256": "db0e0cd1dc136a05abf97c28072edfda4b9cd8de3a0bf1e45fd45747655dcef5",
|
||||
"function": "_IDirect3DDevice8_SetVertexShaderConstant@16",
|
||||
"recipe": "xdk-stock-d3dinline",
|
||||
"source_recipe": "stock XDK D3DINLINE (static __forceinline)",
|
||||
"target_evidence_sha256": "cc42796796437d1eaee75aa6b6a300dc712d6d48cb2571820adf13f5eea7a3bd",
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox_text"
|
||||
}
|
||||
],
|
||||
"schema_version": 1
|
||||
}
|
||||
-113827
File diff suppressed because it is too large.
Load diff
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"version": 1,
|
||||
"entries": []
|
||||
}
|
||||
@@ -1,581 +0,0 @@
|
||||
[
|
||||
{
|
||||
"unit": "source/shell/shell_xbox",
|
||||
"group": "aligned-rdata",
|
||||
"reason": "the complete rebuilt object owns the exact two string COMDATs and compiler-generated SEH scope table; the grouped verifier proves each payload, alignment-derived padded extent, flags, owner snapshot, relocation address/type, and source-relative handler destination while objdiff merges the aligned sections and attributes the private scope-table labels differently",
|
||||
"members": [
|
||||
{
|
||||
"symbol": "??_C@_06GAOAIMNN@xdemo?5?$AA@",
|
||||
"measurements": {
|
||||
"target": {
|
||||
"section": ".rdata",
|
||||
"size": 7,
|
||||
"padded_size": 8,
|
||||
"flags": 1076891712,
|
||||
"relocation_count": 0,
|
||||
"normalized_sha256": "2d636beaf6ef18262eb352ea8a00f3b1b0ee3628666eb07e679892eca5f08b5e",
|
||||
"owner": { "value": 0, "type": 0, "storage": 2 }
|
||||
},
|
||||
"base": {
|
||||
"section": ".rdata",
|
||||
"size": 7,
|
||||
"padded_size": 8,
|
||||
"flags": 1076891712,
|
||||
"relocation_count": 0,
|
||||
"normalized_sha256": "2d636beaf6ef18262eb352ea8a00f3b1b0ee3628666eb07e679892eca5f08b5e",
|
||||
"owner": { "value": 0, "type": 0, "storage": 2 }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"symbol": "??_C@_06PFFNFMJI@XDEMOS?$AA@",
|
||||
"measurements": {
|
||||
"target": {
|
||||
"section": ".rdata",
|
||||
"size": 7,
|
||||
"padded_size": 8,
|
||||
"flags": 1076891712,
|
||||
"relocation_count": 0,
|
||||
"normalized_sha256": "798ec2f79c908eed7153344688b0def452386891f2deae50826a2658182e9bd5",
|
||||
"owner": { "value": 0, "type": 0, "storage": 2 }
|
||||
},
|
||||
"base": {
|
||||
"section": ".rdata",
|
||||
"size": 7,
|
||||
"padded_size": 8,
|
||||
"flags": 1076891712,
|
||||
"relocation_count": 0,
|
||||
"normalized_sha256": "798ec2f79c908eed7153344688b0def452386891f2deae50826a2658182e9bd5",
|
||||
"owner": { "value": 0, "type": 0, "storage": 2 }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"symbol": "_rdata_002a0a88",
|
||||
"base_symbol": "$T18302",
|
||||
"source_function": "_main",
|
||||
"measurements": {
|
||||
"target": {
|
||||
"section": ".rdata",
|
||||
"size": 12,
|
||||
"padded_size": 16,
|
||||
"flags": 1077940288,
|
||||
"relocation_count": 2,
|
||||
"normalized_sha256": "3414421b183188342209566fad4e0c0723070b4030630dde685ba70281e92725",
|
||||
"owner": { "value": 0, "type": 0, "storage": 2 }
|
||||
},
|
||||
"base": {
|
||||
"section": ".rdata",
|
||||
"size": 12,
|
||||
"padded_size": 16,
|
||||
"flags": 1077940288,
|
||||
"relocation_count": 2,
|
||||
"normalized_sha256": "3414421b183188342209566fad4e0c0723070b4030630dde685ba70281e92725",
|
||||
"owner": { "value": 0, "type": 0, "storage": 3 }
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"unit": "libs/libcmt/crt0msg",
|
||||
"symbol": "_rterrs",
|
||||
"reason": "The first-party XDK names the private runtime-error table rterrs. January and the rebuilt object have identical 144-byte data, all 18 relocation sites and types, and independently resolved string destinations; objdiff undercredits the aggregate despite exact COFF section comparison.",
|
||||
"measurements": {
|
||||
"size": 144,
|
||||
"relocation_count": 18,
|
||||
"normalized_sha256": "25298d4d1ea85dfa6a4696577658216429876d7b7b59ed245667db872d9d79d2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/camera/editor_flying_camera",
|
||||
"group": "camera-static-sections",
|
||||
"allow_incomplete_unit": true,
|
||||
"credit_raw_size": true,
|
||||
"reason": "January and the rebuilt object have identical 124-byte private .bss and 52-byte .data payloads, flags, alignments, and owner storage. The nine .data relocations resolve to the same image destinations. HCEX names the separate file statics and their definition order; the January .bss offsets corroborate their exact layout. Objdiff undercredits the two sections after the authentic private-state split. Credit raw sizes because its report scores .bss as 124 bytes, not the 128-byte alignment-derived padded extent.",
|
||||
"members": [
|
||||
{
|
||||
"symbol": "_is_scripted",
|
||||
"measurements": {
|
||||
"target": {
|
||||
"section": ".bss", "size": 124, "padded_size": 128,
|
||||
"flags": 3225419904, "relocation_count": 0,
|
||||
"normalized_sha256": "7b8ec8dd836b564f0c85ad088fc744de820345204e154bc1503e04e9d6fdd9f1",
|
||||
"owner": { "value": 0, "type": 0, "storage": 3 }
|
||||
},
|
||||
"base": {
|
||||
"section": ".bss", "size": 124, "padded_size": 128,
|
||||
"flags": 3225419904, "relocation_count": 0,
|
||||
"normalized_sha256": "7b8ec8dd836b564f0c85ad088fc744de820345204e154bc1503e04e9d6fdd9f1",
|
||||
"owner": { "value": 0, "type": 0, "storage": 3 }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"symbol": "_editor_camera_speed",
|
||||
"measurements": {
|
||||
"target": {
|
||||
"section": ".data", "size": 52, "padded_size": 52,
|
||||
"flags": 3224371264, "relocation_count": 9,
|
||||
"normalized_sha256": "22486dfe6b955caf557fcbca418621432912c2d3012afd4e6031fe22b880d07b",
|
||||
"owner": { "value": 0, "type": 0, "storage": 3 }
|
||||
},
|
||||
"base": {
|
||||
"section": ".data", "size": 52, "padded_size": 52,
|
||||
"flags": 3224371264, "relocation_count": 9,
|
||||
"normalized_sha256": "22486dfe6b955caf557fcbca418621432912c2d3012afd4e6031fe22b880d07b",
|
||||
"owner": { "value": 0, "type": 0, "storage": 3 }
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"unit": "source/units/unit_dialogue",
|
||||
"symbol": "_global_speech_priority_names",
|
||||
"reason": "January and the rebuilt 44-byte speech-name table have identical payload, 11 relocation sites and types, and independently resolved literal destinations; objdiff undercredits the table because the executable split assigns nine folded SELECT_ANY strings to other objects",
|
||||
"measurements": {
|
||||
"size": 44,
|
||||
"relocation_count": 11,
|
||||
"normalized_sha256": "85759b3811ff7dc47b03792ac85317be51431a3f9e01dcafce317ed736a391b0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/game/game_allegiance",
|
||||
"symbol": "_global_game_team_names",
|
||||
"reason": "The 40-byte January and rebuilt team-name tables have identical normalized payload, owner storage and flags, and all ten relocations resolve independently to the same image destinations; objdiff undercredits this sole unmatched section.",
|
||||
"measurements": {
|
||||
"size": 40,
|
||||
"relocation_count": 10,
|
||||
"normalized_sha256": "2c34ce1df23b838c5abf2a7f6437cca3d3067ed509ff25f11df6b11b582b51eb"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/game/game_engine_slayer",
|
||||
"symbol": "_slayer_engine",
|
||||
"reason": "The 136-byte January and rebuilt engine tables have identical normalized payload, external owner storage and section flags, and all 24 relocations resolve independently to the same image destinations; objdiff undercredits this sole unmatched section.",
|
||||
"measurements": {
|
||||
"size": 136,
|
||||
"relocation_count": 24,
|
||||
"normalized_sha256": "cd47b29508fea4e4c11451792c17f629a9ad240b3c3df5c889c0d416c378bc78"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/hud_definitions",
|
||||
"symbol": "_global_hud_anchor_names",
|
||||
"reason": "The 20-byte January and rebuilt HUD anchor-name tables have identical normalized payload, owner storage and flags, and all five relocations resolve independently to the same image destinations; objdiff undercredits this sole unmatched section.",
|
||||
"measurements": {
|
||||
"size": 20,
|
||||
"relocation_count": 5,
|
||||
"normalized_sha256": "de47c9b27eb8d300dbb5f2c353e632c393262cf06340c4fa7f1b40c4cbd36f90"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/structures/leaf_map",
|
||||
"symbol": "_leaf_map_initialize_section",
|
||||
"allow_incomplete_unit": true,
|
||||
"reason": "January and rebuilt profile-section data have identical 2512-byte payload, section flags and static owner, with all 28 relocations independently resolving to the same image destinations; objdiff undercredits this sole unmatched section.",
|
||||
"measurements": {
|
||||
"size": 2512,
|
||||
"relocation_count": 28,
|
||||
"normalized_sha256": "34570fc43b6cae2795503a6a62861e9a42ce856cb74d895ba7fa6174f1bda68b"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/game/game_engine_race",
|
||||
"symbol": "_race_engine",
|
||||
"reason": "January and rebuilt race-engine tables have identical 136-byte payload, section flags and external owner, with all 25 relocations independently resolving to the same image destinations; objdiff undercredits this sole unmatched section.",
|
||||
"measurements": {
|
||||
"size": 136,
|
||||
"relocation_count": 25,
|
||||
"normalized_sha256": "97a4c632a978acafd20933da4504d8ec3fdf3c5afd2f78934bced57dc8f746f4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/game/game_engine_ctf",
|
||||
"symbol": "_ctf_engine",
|
||||
"reason": "January and rebuilt CTF-engine tables have identical 136-byte payload, section flags and external owner, with all 28 relocations independently resolving to the same image destinations; objdiff undercredits this sole unmatched section.",
|
||||
"measurements": {
|
||||
"size": 136,
|
||||
"relocation_count": 28,
|
||||
"normalized_sha256": "45c41730d038fd3f985f7ccfd8a7e04aa02e2db549ac941386e7cd04c1e1d8c1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_print",
|
||||
"symbol": "_tif_print_rcsid",
|
||||
"reason": "The 164-byte January and rebuilt libtiff data section has identical payload, flags and external owner, and all 18 relocations independently resolve to the same image destinations; objdiff undercredits its sole unmatched section.",
|
||||
"measurements": {
|
||||
"size": 164,
|
||||
"relocation_count": 18,
|
||||
"normalized_sha256": "a81bb4fa00f599a245c1e6b636a2a630629557f2c86f92e2960cf3e16ed94e23"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/memory/zlib/zutil",
|
||||
"symbol": "_z_errmsg",
|
||||
"reason": "The 44-byte January and rebuilt zlib error table has identical payload, flags and external owner, and all ten relocations independently resolve to the same image destinations; objdiff undercredits its sole unmatched section.",
|
||||
"measurements": {
|
||||
"size": 44,
|
||||
"relocation_count": 10,
|
||||
"normalized_sha256": "966ef500de11387122d16ed112b63eb8562f81fc0e67d6f8f4d190766cf1e6ae"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/memory/zlib/deflate",
|
||||
"symbol": "?my_version@?1??deflateInit2_@@9@9",
|
||||
"reason": "The four-byte January and rebuilt zlib version pointer has identical payload, flags and static owner; its relocation independently resolves to the same image destination despite objdiff's alias attribution.",
|
||||
"measurements": {
|
||||
"size": 4,
|
||||
"relocation_count": 1,
|
||||
"normalized_sha256": "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/networking/network_server_manager",
|
||||
"symbol": "_network_game_server_memory_do_not_use_directly_in_use",
|
||||
"reason": "January and rebuilt eight-byte BSS owner have identical extent, flags, external storage and section-relative layout with no relocations; objdiff undercredits this sole unmatched section.",
|
||||
"measurements": {
|
||||
"size": 8,
|
||||
"relocation_count": 0,
|
||||
"normalized_sha256": "af5570f5a1810b7af78caf4bc70a660f0df51e42baf91d4de5b2328de0e83dfc"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/game/game_engine_oddball",
|
||||
"symbol": "_oddball_engine",
|
||||
"reason": "January and rebuilt Oddball engine tables have identical 136-byte payload, flags and owner storage, with all 27 relocations independently resolving to the same image destinations; objdiff undercredits the sole unmatched data section.",
|
||||
"measurements": {
|
||||
"size": 136,
|
||||
"relocation_count": 27,
|
||||
"normalized_sha256": "ffe1ef0aa827017276299f3a497655019d91f94374129c31634061500e5ae4b9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/game/game_globals",
|
||||
"symbol": "_global_material_type_strings",
|
||||
"reason": "January and rebuilt material-name tables have identical 132-byte payload, flags and owner storage, with all 33 relocations independently resolving to the same image destinations; objdiff undercredits the sole unmatched data section.",
|
||||
"measurements": {
|
||||
"size": 132,
|
||||
"relocation_count": 33,
|
||||
"normalized_sha256": "115bad14f1c9f2c027a84de21b107015722cb76be8d0abf3760ad8e00d6c24a5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/items/projectile_definitions",
|
||||
"symbol": "_default_projectile_material_response",
|
||||
"reason": "January and rebuilt projectile material tables have identical 160-byte payload, flags and owner storage, with all three relocations independently resolving to the same image destinations; objdiff undercredits the sole unmatched data section.",
|
||||
"measurements": {
|
||||
"size": 160,
|
||||
"relocation_count": 3,
|
||||
"normalized_sha256": "b71e2246c2d39831ad65f2b9570fecb59a1a0d743278b63cc125b118c148f6b9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/memory/byte_swapping",
|
||||
"symbol": "_byte_bs_codes",
|
||||
"reason": "January and rebuilt byte-swap tables have identical 144-byte payload, flags and owner storage, with all eight relocations independently resolving to the same image destinations; objdiff undercredits the sole unmatched data section.",
|
||||
"measurements": {
|
||||
"size": 144,
|
||||
"relocation_count": 8,
|
||||
"normalized_sha256": "fc892f5c359e0165aa8cdbd745b191928baac3213935c79d8699cdcba32468d0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/physics/collision_bsp_definitions",
|
||||
"symbol": "_global_collision_bsp_definition_data",
|
||||
"reason": "January and rebuilt collision BSP definition tables have identical 900-byte payload, flags and owner storage, with all 68 relocations independently resolving to the same image destinations; objdiff undercredits the sole unmatched data section.",
|
||||
"measurements": {
|
||||
"size": 900,
|
||||
"relocation_count": 68,
|
||||
"normalized_sha256": "3ed97b7cf09b09837ca36461d74c21909d34106d563a7b914aaffd7c51cf3e56"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/physics/collision_usage",
|
||||
"symbol": "_global_collision_function_names",
|
||||
"reason": "January and rebuilt collision function-name tables have identical 138-byte payload, flags and owner storage, with all 30 relocations independently resolving to the same image destinations; objdiff undercredits the sole unmatched data section.",
|
||||
"measurements": {
|
||||
"size": 138,
|
||||
"relocation_count": 30,
|
||||
"normalized_sha256": "804797955ced17a1f6b1e4b86c0a83a5d25fcb03fa846e690dae51ef13bc5c2f"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/render/render_particles",
|
||||
"symbol": "_render_particles_section",
|
||||
"reason": "The January and rebuilt render-particles profile-section owners have equal 1528-byte payload, section flags and external storage, and their sole relocation independently resolves to the same image string; objdiff undercredits the complete section. All three target functions are strict exact, and base-only SELECT_ANY literals have byte-identical January-selected providers with passing ordinary pair links.",
|
||||
"measurements": {
|
||||
"size": 1528,
|
||||
"relocation_count": 1,
|
||||
"normalized_sha256": "806638334fff1341360b4dec7db0987871f376bc3999e26ff4bcd3a1755d2955"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/bitmaps",
|
||||
"symbol": "_global_vector_palette",
|
||||
"reason": "January and rebuilt 1116-byte palette data have equal payload, section flags, owner storage and offsets, and all 21 relocations resolve to the same image destinations. All 34 target functions are strict exact; the sole extra fast_ftol COMDAT is byte-identical to its selected January provider and pair-links in either order.",
|
||||
"measurements": {
|
||||
"size": 1116,
|
||||
"relocation_count": 21,
|
||||
"normalized_sha256": "443063631e6958ff5026be3038f8785d61eee4073cb01b8eaa4fdfcc3b620002"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/game/cheats",
|
||||
"symbol": "_cheat_strings",
|
||||
"reason": "January and rebuilt cheats BSS have equal 3201-byte extent, section flags, external owner, zero relocations and matching section-relative symbol layout. The two private function names come from the first-party HCEA SHIP PDB; the string array has a descriptive inferred name, and the trailing unreferenced byte is disclosed as name-unknown rather than credited as a separate owner. All 14 target functions are strict exact and candidate-only providers pass bounded links in both orders.",
|
||||
"measurements": {
|
||||
"size": 3201,
|
||||
"relocation_count": 0,
|
||||
"normalized_sha256": "76d6c353527d212ec3799ea375f945e3ae3760257bd2ef5a75441090df0ddfac"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/items/items",
|
||||
"symbol": "_item_update_section",
|
||||
"reason": "January and rebuilt item-update profile owners have equal 1528-byte payload, section flags, external owner and one resolved image relocation. All 18 target functions and eight target-owned noncode symbols are strict exact. The only former link conflict was the hand-written add_vectors3d provider in ActorCombat; its genuine shared-header inline now emits the same code as SELECT_ANY without changing any ActorCombat function or park. All 42 candidate-only helper/literal copies equal their January-selected providers and 26 ordinary provider-pair links pass in both orders.",
|
||||
"measurements": {
|
||||
"size": 1528,
|
||||
"relocation_count": 1,
|
||||
"normalized_sha256": "806638334fff1341360b4dec7db0987871f376bc3999e26ff4bcd3a1755d2955"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/hud",
|
||||
"symbol": "_default_string",
|
||||
"reason": "January and rebuilt HUD own the same four-byte external data pointer, section flags and relocation destination: the two-zero-byte string selected from GameEngine. All 22 target functions are strict exact. Five candidate-only genuine shared-header inline helpers match their January-selected copies byte-for-byte and ordinary provider-pair links pass in both orders, so these folded copies receive no separate credit.",
|
||||
"measurements": {
|
||||
"size": 4,
|
||||
"relocation_count": 1,
|
||||
"normalized_sha256": "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/effects/particles",
|
||||
"symbol": "_particles_update_section",
|
||||
"reason": "January and rebuilt particles own the same 1536-byte static data section with three image-equivalent relocations, flags and payload. Its eight-byte collision-scale bounds also have identical payload, flags and the external linkage January requires. All 20 target functions are strict exact; genuine shared-header helper providers now link in both orders after removing duplicate hand-written bodies from DebugMemory, Contrails and BoredCamera. Candidate-only folded helper copies receive no separate credit.",
|
||||
"measurements": {
|
||||
"size": 1536,
|
||||
"relocation_count": 3,
|
||||
"normalized_sha256": "6d9398e131ef72b9a6ffc2321c22d27a3e2db1a458385b77b08ba0657a56c74f"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/ai_scenario_definitions",
|
||||
"symbol": "_global_ai_default_state_names",
|
||||
"reason": "January and rebuilt 48-byte AI default-state name table (sole .data section) have identical normalized payload and flags (c0300040), a PDB-public external owner at offset 0, and all 12 relocations resolve to the same image addresses. The whole object otherwise matches: 4/4 functions strict exact, every January-owned section and symbol equal, and all candidate-only literals pair-link with their selected providers in both orders. objdiff 3.3.1 misreads the identical '$' literal names.",
|
||||
"measurements": {
|
||||
"size": 48,
|
||||
"relocation_count": 12,
|
||||
"normalized_sha256": "17b0761f87b081d5cf10757ccc89f12be355c70e2e29df288b65b30710dcbcd1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/ai_profile",
|
||||
"symbol": "_global_ai_meter_definitions",
|
||||
"reason": "January and rebuilt 236-byte AI meter/profile-name .data section (sole data section; _ai_profile_render_spray_names static at +224 on both sides) have identical normalized payload and flags (c0400040), and all 10 relocations resolve to the same image addresses. The whole object otherwise matches: 23/23 functions strict exact, every January-owned section and symbol equal and consistent with cachebeta.pdb publics, and candidate-only literals pair-link with their selected providers in both orders.",
|
||||
"measurements": {
|
||||
"size": 236,
|
||||
"relocation_count": 10,
|
||||
"normalized_sha256": "3a69a8b8a83037c3277fa86c09c7aa4e9b9da8b480e3facb87275548ee4c88b8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/shaders/shader_definitions",
|
||||
"symbol": "_global_shader_effect_additive",
|
||||
"reason": "January and rebuilt 364-byte shader-effect .data section (the additive and alpha-blended effect definitions, the latter at +184 on both sides) have identical normalized payload and flags (c0400040), and both relocations resolve to the same image addresses. The whole object otherwise matches: 1/1 function strict exact, every January-owned section and symbol equal and consistent with cachebeta.pdb publics, and candidate-only literals pair-link with their selected providers in both orders.",
|
||||
"measurements": {
|
||||
"size": 364,
|
||||
"relocation_count": 2,
|
||||
"normalized_sha256": "8bbb21a994d2ec5051de3ea76497f648469fe42d5f6aa7da85f3b598bf16bcd0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/units/dialogue_definitions",
|
||||
"symbol": "_dialogue_vocalization_type_name",
|
||||
"reason": "January and rebuilt 1,672-byte dialogue .data section have identical normalized payload and flags (c0400040), and all 418 relocations resolve to the same image addresses. The whole object otherwise matches: 2/2 functions strict exact, all 298 January symbols equal in section, offset and storage and consistent with cachebeta.pdb publics, and all candidate-only literals pair-link with their selected providers in both orders.",
|
||||
"measurements": {
|
||||
"size": 1672,
|
||||
"relocation_count": 418,
|
||||
"normalized_sha256": "256984cb62bc879971463ff0ff7567042dc95d8b0fb2bc676f246c2293c77ae8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/actor_types",
|
||||
"symbol": "_global_actor_type_names",
|
||||
"reason": "January and rebuilt 128-byte actor-type .data section (the static actor_type_definitions table at +0 and the public global_actor_type_names at +64) have identical normalized payload and flags (c0400040), and all 32 relocations resolve to the same image addresses. Ownership was corrected first: cachebeta.pdb publics prove actor_type_definitions and its accessor actor_type_definition_get file-static. January's own assert strings name actor_type_definitions; the Halo CE atlas names the accessor at the same 0x140-byte span. All 13 functions are strict exact and every January-owned section and symbol matches.",
|
||||
"measurements": {
|
||||
"size": 128,
|
||||
"relocation_count": 32,
|
||||
"normalized_sha256": "38723a2e5e8a17aa7950dc008209944e898f69a7bd10a23c839d341e935fd5ca"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/cutscene/recorded_animation_definitions",
|
||||
"symbol": "_recorded_animation_event_stream_data",
|
||||
"reason": "January and rebuilt 180-byte recorded-animation tag .data section have identical normalized payload and flags (c0400040), and all 11 relocations resolve to the same image addresses. Ownership was corrected first: byte_swap_recording is absent from cachebeta.pdb publics and referenced by no other January object, so it is file-static. Both functions are strict exact and every January-owned section and symbol matches.",
|
||||
"measurements": {
|
||||
"size": 180,
|
||||
"relocation_count": 11,
|
||||
"normalized_sha256": "c83e71991a0ac6309173102325bf6a194d27d5d80cdc9a395ed954c80bae3d5d"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/models/model_animation_definitions",
|
||||
"symbol": "_weapon_type_animation_list",
|
||||
"reason": "January and rebuilt 1,288-byte animation-list .data section have identical normalized payload and flags (c0400040), and all 170 relocations resolve to the same image addresses. Ownership was corrected first: the seven *_animation_list_entries arrays are absent from cachebeta.pdb publics and referenced by no other January object, so they are file-static beside their public animation_list wrappers. All three functions are strict exact and all 139 January symbols match.",
|
||||
"measurements": {
|
||||
"size": 1288,
|
||||
"relocation_count": 170,
|
||||
"normalized_sha256": "76f074030d3cb6940a74673504f664555bd5d02087282c01338c8b83fe3d1654"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/sound/sound_classes",
|
||||
"symbol": "_sound_classes",
|
||||
"reason": "January and rebuilt 2,452-byte sound-class .data section have identical normalized payload and flags (c0400040), and all 51 relocations resolve to the same image addresses. Ownership was corrected first: the static accessor at 0x1b84c0 is absent from cachebeta.pdb publics and is named sound_class_datum_get by the Halo CE atlas, anchored on six already-exact sound_classes symbols. All 12 functions are strict exact and every January-owned section and symbol matches.",
|
||||
"measurements": {
|
||||
"size": 2452,
|
||||
"relocation_count": 51,
|
||||
"normalized_sha256": "1ae64de7abb95c40952d3aacf88c68232070d4c19906bf32dfc8877bd6725abc"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/objects/object_types",
|
||||
"symbol": "_object_data_definition",
|
||||
"reason": "January and rebuilt 2,608-byte object-type tag .data section have identical normalized payload and flags (c0400040), and all 190 relocations resolve to the same image addresses. Ownership was corrected first: HCEX.pdb names the sole object_types file static processed_bsp_flags (unsigned short), absent from cachebeta.pdb publics. All 31 functions are strict exact and all 66 January symbols match. All eight candidate-only helper COMDATs are byte-identical to January's selected copies and pair-link in both orders; items' hand-written valid_real_matrix4x3/valid_real_vector3d_axes3 NODUP providers were replaced by the genuine real_math.h inlines.",
|
||||
"measurements": {
|
||||
"size": 2608,
|
||||
"relocation_count": 190,
|
||||
"normalized_sha256": "205043014fcdf8e45147d168ae70e43cda7814dfc63f1c1dade93f2c0f9f4341"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/hs/hs_scenario_definitions",
|
||||
"symbol": "_hs_script_types_enum",
|
||||
"reason": "January and rebuilt HS scenario .data have identical 628-byte normalized payload, all 33 relocation identities, and 8-byte section alignment (c0400040). The original nine public definitions retain their target offsets and storage. Separate typed field and byte-swap arrays replace invented packed aggregates and padding; the byte-swap function is genuinely file-static. The one target function remains strict exact, and there are no surplus external definitions.",
|
||||
"measurements": {
|
||||
"size": 628,
|
||||
"relocation_count": 33,
|
||||
"normalized_sha256": "a1add12fc2ddd7afb3935997f9e1532b27a3887f8e85e914db954d1665547c09"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/hs/hs_globals_external",
|
||||
"symbol": "_screenshot_size_definition",
|
||||
"reason": "January and rebuilt HS external-global .data have identical 7,076-byte normalized payload, section flags (c0400040), and all 1,322 relocation identities. The invented 442-element definition aggregate has been replaced by 442 separate file-static typed definitions in January's proven 12-byte record order; the public hs_external_globals table remains at +5304. The 2011 first-party HCEX PDB independently attests 427 unique definition names and their type; the 15 older-only names are descriptive names derived from their January string records, not claimed originals. January and rebuilt first-record storage are file-static, and the unit emits no code or candidate-only external owner.",
|
||||
"measurements": {
|
||||
"size": 7076,
|
||||
"relocation_count": 1322,
|
||||
"normalized_sha256": "1e4346aef4491a55772f4f51a6989e06074dc5245a2c01aa1be97fb2e221ae8c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"symbol": "_event_handler_functions",
|
||||
"reason": "January and rebuilt 934-byte event-handler .data section (the static event_handler_function_list name/function table at +0 and the public event_handler_functions at +816) have identical normalized payload and flags (c0400040), and all 228 relocations resolve to the same image addresses. The 366-byte .bss is also identical. Ownership was corrected first: 98 handler functions, event_handler_function_list and new_campaign_profile_name are absent from cachebeta.pdb publics and referenced by no other January object, so they are file-static. All 100 functions are strict exact and all 452 January symbols match. The three stock D3D SDK .rdata tables it also emits are byte-identical to January's selected copies and pair-link in both orders, as in the 54 already-admitted objects that emit them.",
|
||||
"measurements": {
|
||||
"size": 934,
|
||||
"relocation_count": 228,
|
||||
"normalized_sha256": "c1040d667c392fd772fab34335ade456dac49ae864a8200c4560df63cec186fd"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/objects/objects",
|
||||
"symbol": "?section@?1??objects_update@@9@9",
|
||||
"reason": "objects_update's function-static section table: January and the rebuilt object have identical 1,530-byte .data, relocation site/type and independently resolved string destination; objdiff 3.3.1's '$'-literal relocation-name defect undercredits it despite exact COFF section comparison. Whole object admitted after the Layer 1 provider repairs (action_charge, player_control, bored_camera, path_obstacles, decals) replaced hand-written NODUP helper copies with the genuine real_math.h inlines: all 121 functions strict exact, 225 symbols match storage/offsets and cachebeta.pdb publics, 26 candidate-only helper COMDATs byte-identical to January's selected copies and pair-linking in both orders.",
|
||||
"measurements": {
|
||||
"size": 1530,
|
||||
"relocation_count": 1,
|
||||
"normalized_sha256": "e94bb79478c95dce11c4a1f720a07ccbaa3a8d18b84acbe5605472d6f8635b74"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/units/units",
|
||||
"symbol": "_magic_base_animation_seat_index",
|
||||
"reason": "units' writable .data section (magic_base_animation_seat_index, unit_update_section, unit_update's last_time and base_seat_labels): January and the rebuilt object have identical 1,564-byte payload, 7 relocation sites/types and independently resolved string destinations (5 of the 7 base_seat_labels strings are selected in other January objects and pair-link cleanly); objdiff 3.3.1's '$'-literal relocation-name defect undercredits it despite exact COFF section comparison. Whole object admitted: all 189 functions strict exact; the 25 code_ placeholders carry their first-party names (HCEX_Release.pdb units compiland, Sept-2001 map, January atlas) and all 50 file-statics carry static storage per cachebeta.pdb publics, so 321 symbols match storage/offsets; 97 candidate-only surplus definitions (31 helper COMDATs byte-identical to January's selected copies, SDK tables, literals) pair-link with their selected providers in both orders; _point_from_line3d is referenced out of line by January's units.obj (owner ruling 20260921 #1).",
|
||||
"measurements": {
|
||||
"size": 1564,
|
||||
"relocation_count": 7,
|
||||
"normalized_sha256": "6ed61c39a648905cf23b12b916e2adadfe97b6e5aa492c29a14c7265809ef1a7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/items/projectiles",
|
||||
"symbol": "_projectile_update_section",
|
||||
"allow_incomplete_unit": true,
|
||||
"reason": "January and rebuilt projectile-update profile-section data have identical 1548-byte payload, section flags and static owners (_projectile_update_section at 0, _effect_marker_names at 1528), with all six relocations independently resolving to the same image destinations; January's split leaves the pooled normal and gravity literals undefined while the rebuilt object emits identical select-any copies, and objdiff 3.3.1's '$'-literal name defect undercredits this sole unmatched section. The unit's .rdata is already 100%; the parked _projectile_new residual keeps the unit incomplete and receives no credit from this entry.",
|
||||
"measurements": {
|
||||
"size": 1548,
|
||||
"relocation_count": 6,
|
||||
"normalized_sha256": "7bfaf5fb0b0c9e0593153885a81788bc8b118a9651a60a8a94e5ffd9fd203cf2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/math/periodic_functions",
|
||||
"symbol": "_global_periodic_functions_enum_strings",
|
||||
"allow_incomplete_unit": true,
|
||||
"reason": "The January and rebuilt 96-byte periodic/transition enum .data have identical normalized payload, owner storage and flags, and all 20 relocations resolve to the same image destinations. Objdiff 3.3.1 undercredits folded string literals. The variable-period builder remains parked and earns no code credit.",
|
||||
"measurements": {
|
||||
"size": 96,
|
||||
"relocation_count": 20,
|
||||
"normalized_sha256": "8fdd4bf9e8be002fe8938ee0849dfec244c27138f7b77eff28ec8ba7b4538614"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/objects/object_lights",
|
||||
"symbol": "_lights_section",
|
||||
"allow_incomplete_unit": true,
|
||||
"reason": "object_lights' writable .data (the static lights_section profile section at +0 and the four public object_light_* tuning globals at +1528..+1540): January and the rebuilt object have identical 1,541-byte payload, owner storage and flags (c0400040), and its single relocation (the 'render_lights' string, selected in hs) resolves independently to the same image destination; objdiff 3.3.1's '$'-literal relocation-name defect undercredits it despite exact COFF section comparison. All 43 functions are strict exact; should_render_lights, light_attenuation and cluster_get_first/next_light are file-static per cachebeta.pdb publics (no January reference outside the object; should_render_lights is the /Od-attested call in lights_render_diffuse and lights_render_specular), so all 71 January symbols match storage and offsets; the 12 candidate-only helper COMDATs pair-link with their selected providers in both orders. The unit is not marked Matching only because its _object_get_bounding_sphere COMDAT differs from action_vehicle's selected copy in its two __FILE__ literal relocations (January object_lights' own 'c:\\halo\\source\\objects\\objects.h' literal; held owner item), so this sole unmatched section is credited with an explicit incomplete-unit opt-in.",
|
||||
"measurements": {
|
||||
"size": 1541,
|
||||
"relocation_count": 1,
|
||||
"normalized_sha256": "527b43a173f528444fa4423af92d7d58a83f2afe7fc1661b6d297401b2760f71"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/bitmap_group",
|
||||
"symbol": "_global_bitmap_reference",
|
||||
"allow_incomplete_unit": true,
|
||||
"reason": "January and rebuilt bitmap_group writable .data (the public global_bitmap_reference/_optional, bitmap_pixel_data, color_plate_data and bitmap_group tag definitions plus their static field/enum tables, 31 owners) have identical 1,424-byte payload, flags (c0400040) and owner storage, and all 152 relocations independently resolve to the same image destinations. January's split leaves the empty-string and 'default' literals undefined (linker-selected in other objects) while the rebuilt object emits identical select-any copies, so objdiff 3.3.1's '$'-literal name defect undercredits this sole unmatched section; renaming only the '$' inside literal names on both sides scores it 100.0 with the production objdiff binary. The parked _bitmap_group_add_bitmap residual keeps the unit incomplete, so this entry opts in explicitly as an incomplete unit and grants no function or object credit.",
|
||||
"measurements": {
|
||||
"size": 1424,
|
||||
"relocation_count": 152,
|
||||
"normalized_sha256": "df5c6d69f4e13ea6df9398e2b5cc5c4455410b077b5ba6763930c4dd748505cb"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/ai_communication",
|
||||
"symbol": "_global_communication_priority_names",
|
||||
"allow_incomplete_unit": true,
|
||||
"reason": "January and rebuilt ai_communication .data (the public global_communication_priority_names, global_communication_team_names and global_communication_type_names string tables at +0/+32/+48) have identical 276-byte payload, flags (c0400040) and owner storage, and all 69 relocations independently resolve to the same image destinations. January's split leaves six literals ('none', 'shout', 'damage', 'cover', 'flee', 'berserk') undefined because the linker selected other objects' copies, while the rebuilt object emits identical select-any copies, so objdiff 3.3.1's '$'-literal name defect undercredits this sole unmatched section; renaming only the '$' inside literal names on both sides scores it 100.0 with the production objdiff binary. _ai_communication_actor_talk_weight (parked) and _ai_communication_event remain residual, so this entry opts in explicitly as an incomplete unit and grants no function or object credit.",
|
||||
"measurements": {
|
||||
"size": 276,
|
||||
"relocation_count": 69,
|
||||
"normalized_sha256": "d489001ff88ed206b56f44bd0789a8332510f33bf40a312a7b2e5d60c3fe3e03"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/ai_debug",
|
||||
"symbol": "_global_ai_debug_firing_position_color_count",
|
||||
"allow_incomplete_unit": true,
|
||||
"reason": "January and rebuilt ai_debug .data (the public global_ai_debug_firing_position_color_count at +0, the file-static postcombat type-name table at +4 and the two file-static selected-squad globals at +48/+52) have identical 56-byte payload, flags (c0300040) and owner storage, and all 11 relocations independently resolve to the same image destinations. January's split leaves the 'none' literal undefined because the linker selected another object's copy, while the rebuilt object emits an identical select-any copy, so objdiff 3.3.1's '$'-literal name defect undercredits this sole unmatched section; renaming only the '$' inside literal names on both sides scores it 100.0 with the production objdiff binary. _ai_debug_render_actor remains residual, so this entry opts in explicitly as an incomplete unit and grants no function or object credit.",
|
||||
"measurements": {
|
||||
"size": 56,
|
||||
"relocation_count": 11,
|
||||
"normalized_sha256": "3ba0a54a0875e71a01972b13dcf574a4d16d0f1ea3531ef51d98311b5ac7eee5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"unit": "source/game/game_engine_king",
|
||||
"symbol": "_king_engine",
|
||||
"allow_incomplete_unit": true,
|
||||
"reason": "January and rebuilt King engine tables have identical 136-byte payload, section flags (c0400040) and public owner storage (_king_engine is a cachebeta.pdb public), and all 23 relocations (22 engine callbacks and the 'king' name literal) independently resolve to the same image destinations. January's split leaves the 'king' literal undefined because the linker selected game_engine's copy, while the rebuilt object emits an identical select-any copy, so objdiff 3.3.1's '$'-literal name defect undercredits this sole unmatched section; renaming only the '$' inside literal names on both sides scores it 100.0 with the production objdiff binary. All 29 functions are strict exact; the unit stays NonMatching until the owner rules on the whole-object packet (owner queue #13: _find_next_hill's preserved uninitialised no-candidate return, plus the cachebeta storage fix), so this entry opts in explicitly as an incomplete unit, credits only the table's data bytes and certifies nothing about _find_next_hill or object completion.",
|
||||
"measurements": {
|
||||
"size": 136,
|
||||
"relocation_count": 23,
|
||||
"normalized_sha256": "4009f5b6117e9f00cb001a23b9a56b9dc51a694206c442ce715e2bed2d5465a7"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,587 +0,0 @@
|
||||
[
|
||||
{
|
||||
"unit": "source/devices/devices",
|
||||
"function": "_device_export_function_values",
|
||||
"reason": "The scoped Opus reconciliation proves all 512 padded bytes, 21 ordered relocations and normalized SHA-256 7bf0963941ed36b13676536592a3af9d2786f5d4970b56f1129d24c3a35cc968 exact. Objdiff's 94.405594 percent is a compiler-local switch-label representation false negative; credit only the target report's 505 meaningful bytes. The ordinary typed mode loop preserves January's unordered delay predicate and uses the proper devices.h public declaration. No comparator relaxation, byte patch, extra helper, parameter-width trick or whole-object completion claim. See docs/object_matching_logs/devices_obj_export_function_values_opus_reconciliation_20260906.md."
|
||||
},
|
||||
{
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox",
|
||||
"function": "_rasterizer_set_stencil_mode",
|
||||
"reason": "The scoped Opus reconciliation proves all 784 padded/meaningful bytes, 78 ordered relocations and normalized SHA-256 903201d61d15f0c4dcad96fd81acb8049e8bfc201883061924dc95f3eaea8852 exact. Objdiff's 96.65072 percent is a compiler-local switch-label representation false negative. Source applies the debug policy in the public long input domain before narrowing once to the short cached mode, as January's entry dataflow corroborates; no declaration permutation or type/ABI change. Existing data and helper ownership remain separate from this function credit. See docs/object_matching_logs/rasterizer_xbox_obj_three_natural_opus_closures_20260906.md."
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/action_obey",
|
||||
"function": "_action_obey_command_end",
|
||||
"reason": "Independent frozen January/actual COFF comparison proves all 560 padded bytes, 24 ordered relocations and normalized SHA-256 f59f0185a672ce6409fe3d3c3a439e517483593f6ffc9bf5eff4b18dd4420a61 exact. Objdiff reports 85.26786 percent because compiler-local switch labels are represented differently. The ledger credits only the target's 549 meaningful bytes, with no byte/comparator exception. The genuine private body is retained through individual_end, not a fake external ABI. Fable's earlier case-order correction remains documented; this is independently authenticated reconstruction, not a claim of first-shot source. Whole-object math-owner and remaining-source boundaries are separate. See docs/object_matching_logs/action_obey_obj_partial_graph_reconciliation_20260905.md."
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/action_obey",
|
||||
"function": "_action_obey_directmovement_update_facing",
|
||||
"reason": "Independent frozen January/actual COFF comparison proves all 336 meaningful/padded bytes, 17 ordered relocations and normalized SHA-256 17b28fabb3ad4366074689d2f9be1364ccf07cdc0c7a185dbd4dff25b00e3f97 exact. Objdiff reports 96.77419 percent due to compiler-local switch labels. This is strict target-function credit only; no comparator weakening or surplus helper credit. Its real individual_update caller naturally preserves the target cross_product3d/negate_vector3d owners after removing their manual wrapper aliases. Five additional header math owners are explicitly audited and remain a whole-object link/admission boundary. See docs/object_matching_logs/action_obey_obj_partial_graph_reconciliation_20260905.md."
|
||||
},
|
||||
{
|
||||
"unit": "source/input/input_xbox",
|
||||
"function": "_input_key_is_down",
|
||||
"reason": "Independent root and reviewer COFF gates prove all 192 meaningful/padded bytes and 19 ordered relocations exact, normalized SHA-256 c1ab3b0043e411c7e6695fb129837501c3bca12a2477d9497b5123f3eaf17805. Objdiff reports 93.93939 percent because compiler-local switch labels are represented differently. A natural result variable and single terminal return satisfy the house rules without a bogus unreachable fallback and reproduce January; no target-byte exception or declaration-order tuning. See docs/object_matching_logs/input_xbox_obj_public_leaves_independent_review_20260904.md."
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/player_ui",
|
||||
"function": "_set_local_player_controls_from_player_profile",
|
||||
"reason": "Independent strict COFF comparison proves all 528 meaningful/padded bytes and 14 ordered relocations exact, normalized SHA-256 ff47c65c6eda0c31b625817bb914f77ad790244d2be44109e484d10664685ee5. Raw objdiff reports 95.89041 percent due to compiler-local switch labels. This repairs existing function credit only; it does not count fresh reconstruction or waive the object's public playlist-layout/coalescing boundary. See docs/object_matching_logs/player_ui_obj_owner_house_rule_reconciliation_20260904.md."
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/hud_unit",
|
||||
"function": "_hud_render_damage_indicators",
|
||||
"reason": "Independent root/worker COFF gates prove all 688 padded bytes and 39 ordered relocations exact, normalized SHA-256 cf7cb8af78f4f4f9fb2a11c7bb67c2e5fb0e31cedcbe8b062ef7aa7fad4cacd0. Objdiff reports 95.85253 percent because compiler-local switch labels are represented differently; no byte or target exception. The independently PDB/type/ABI-reviewed source and complete emitted-owner audit are documented in docs/object_matching_logs/hud_unit_obj_damage_indicators_exact_20260904.md."
|
||||
},
|
||||
{
|
||||
"unit": "source/networking/network_client_message_handler",
|
||||
"function": "_network_game_client_handle_message",
|
||||
"reason": "Audited January dispatcher is strict exact: 1088 padded/logical bytes, 84 ordered relocations, normalized SHA-256 32ca599a7f9f3eb44546bcd119ce77eb705e9fc745f9d852c16295cbe1f3850f. Objdiff differs only on compiler-local switch labels; no byte or target exception. See docs/object_matching_logs/network_client_message_handler_obj_admission_review_20260904.md."
|
||||
},
|
||||
{
|
||||
"unit": "source/cache/cache_files",
|
||||
"function": "_cache_files_map_directory",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/units/units",
|
||||
"function": "_unit_is_busy",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/text/international_strings",
|
||||
"function": "_double_byte_character",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/shaders/shaders",
|
||||
"function": "_numeric_countdown_timer_get",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/shaders/shaders",
|
||||
"function": "_shader_get_vertex_shader_permutation",
|
||||
"reason": "hardened COFF comparison proves all 288 padded bytes and all 18 semantic relocations exact; objdiff reports a local jump-table label encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/shaders/shaders",
|
||||
"function": "_shader_is_decal",
|
||||
"reason": "hardened COFF comparison proves all 144 padded bytes and all 10 semantic relocations exact; objdiff reports a local jump-table label encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox_errors",
|
||||
"function": "_rasterizer_error",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/networking/network_messages",
|
||||
"function": "_create_network_game_message",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/networking/network_game_globals",
|
||||
"function": "_network_game_client_start_frame",
|
||||
"reason": "hardened COFF comparison proves all 560 padded bytes and all 57 semantic relocations exact; objdiff reports a local jump-table label encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/memory/data_encoding",
|
||||
"function": "_data_decode_array",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/memory/data_encoding",
|
||||
"function": "_data_decode_memory",
|
||||
"reason": "hardened COFF comparison proves all 304 padded bytes and all 19 semantic relocations exact; objdiff reports a local jump-table label encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/memory/data_encoding",
|
||||
"function": "_data_encode_memory",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/memory/data_encoding",
|
||||
"function": "_data_encode_array",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/memory/data_packets",
|
||||
"function": "__data_packet_verify",
|
||||
"reason": "hardened COFF comparison proves all 464 padded bytes and all 27 semantic relocations exact; objdiff reports a local jump-table label encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/memory/data_packets",
|
||||
"function": "__data_packet_encode",
|
||||
"reason": "hardened COFF comparison proves all 768 padded bytes and all 44 semantic relocations exact; objdiff reports a local jump-table label encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/memory/data_packets",
|
||||
"function": "__data_packet_decode",
|
||||
"reason": "hardened COFF comparison proves all 672 padded bytes and all 28 semantic relocations exact; objdiff reports a local jump-table label encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/memory/byte_swapping",
|
||||
"function": "__byte_swap_data",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/memory/zlib/inflate",
|
||||
"function": "_inflate",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/main/console",
|
||||
"function": "_console_update",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_text_search_and_replace_functions",
|
||||
"function": "_widget_controller",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/attract_mode",
|
||||
"function": "_attract_mode_get_localized_movie_path",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/game/game_time",
|
||||
"function": "_game_time_start",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/game/game_time",
|
||||
"function": "_game_time_update",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/devices/device_controls",
|
||||
"function": "_code_00083e30",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/cseries/cseries_windows",
|
||||
"function": "_code_0007cb70",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bungie_net/network/transport_address",
|
||||
"function": "_transport_error_to_string",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_print",
|
||||
"function": "_TIFFPrintDirectory",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_packbits",
|
||||
"function": "_PackBitsEncode",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_next",
|
||||
"function": "_NeXTDecode",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_dir",
|
||||
"function": "_code_00053960",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_dir",
|
||||
"function": "_code_00054160",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_dirwrite",
|
||||
"function": "_TIFFWriteNormalTag",
|
||||
"reason": "hardened COFF comparison proves all 800 padded bytes and all 30 semantic relocations exact; objdiff reports an internal jump-table relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_dirwrite",
|
||||
"function": "_TIFFWriteDirectory",
|
||||
"reason": "hardened COFF comparison proves all 1760 padded bytes and all 56 semantic relocations exact; objdiff reports internal jump-table relocation encoding false negatives"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_aux",
|
||||
"function": "_TIFFVGetFieldDefaulted",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_lzw",
|
||||
"function": "_horizontalAccumulate8",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_lzw",
|
||||
"function": "_horizontalAccumulate16",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_lzw",
|
||||
"function": "_horizontalDifference8",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_lzw",
|
||||
"function": "_horizontalDifference16",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_getimage",
|
||||
"function": "_setorientation",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_getimage",
|
||||
"function": "_code_00058a20",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_getimage",
|
||||
"function": "_code_00058c40",
|
||||
"reason": "hardened COFF comparison proves all 832 padded bytes and all 18 semantic relocations exact; objdiff reports static BSS symbol/relocation ownership false negatives"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_getimage",
|
||||
"function": "_code_00059180",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_getimage",
|
||||
"function": "_put1bitbwtile",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_getimage",
|
||||
"function": "_code_00059df0",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_getimage",
|
||||
"function": "_code_0005a6f0",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_getimage",
|
||||
"function": "_TIFFReadRGBAImage",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_dirread",
|
||||
"function": "_TIFFFetchData",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_dirread",
|
||||
"function": "_TIFFFetchByteArray",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_dirread",
|
||||
"function": "_TIFFFetchNormalTag",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_dirread",
|
||||
"function": "_TIFFReadDirectory",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/actor_type_sentinel",
|
||||
"function": "_sentinel_decide_action",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/actor_type_mounted_weapon",
|
||||
"function": "_mounted_weapon_decide_action",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/actor_type_marine",
|
||||
"function": "_marine_decide_action",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/actor_type_jackal",
|
||||
"function": "_jackal_decide_action",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/actor_type_infection",
|
||||
"function": "_infection_decide_action",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/actor_type_hunter",
|
||||
"function": "_hunter_decide_action",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/actor_type_grunt",
|
||||
"function": "_grunt_decide_action",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/actor_type_flood",
|
||||
"function": "_flood_decide_action",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/actor_type_engineer",
|
||||
"function": "_engineer_decide_action",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/actor_type_elite",
|
||||
"function": "_elite_decide_action",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/actor_type_crew",
|
||||
"function": "_crew_decide_action",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/actor_type_carrier",
|
||||
"function": "_carrier_decide_action",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/action_guard",
|
||||
"function": "_action_guard_speak_post_combat",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/action_guard",
|
||||
"function": "_action_guard_setup_postcombat",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/action_guard",
|
||||
"function": "_action_guard_control",
|
||||
"reason": "hardened COFF comparison proves exact bytes and semantic relocations; objdiff reports a local-label/relocation encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_fax3",
|
||||
"function": "_skiptoeol",
|
||||
"reason": "hardened COFF comparison proves exact bytes and internal jump-table relocations; objdiff reports a local-label ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/bitmaps/libtiff/tif_fax3",
|
||||
"function": "_Fax3Decode2DRow",
|
||||
"reason": "hardened COFF comparison proves exact bytes and uniquely anchored non-code relocation destinations; objdiff reports csplit data-anchor naming false negatives"
|
||||
},
|
||||
{
|
||||
"unit": "source/objects/objects",
|
||||
"function": "_object_compute_node_matrices",
|
||||
"reason": "hardened COFF comparison proves all 6560 padded bytes and all 318 semantic relocations exact; objdiff reports a local-label encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/objects/objects",
|
||||
"function": "$L11841",
|
||||
"owner_function": "_attachments_new",
|
||||
"reason": "the exact owning COMDAT and an internal relocation prove this differently named jump-table label is the same destination"
|
||||
},
|
||||
{
|
||||
"unit": "source/objects/objects",
|
||||
"function": "$L9776",
|
||||
"owner_function": "_object_export_function_values",
|
||||
"reason": "the exact owning COMDAT and an internal relocation prove this differently named jump-table label is the same destination"
|
||||
},
|
||||
{
|
||||
"unit": "source/objects/objects",
|
||||
"function": "$L9764",
|
||||
"owner_function": "_object_export_function_values",
|
||||
"reason": "the exact owning COMDAT and an internal relocation prove this differently named jump-table label is the same destination"
|
||||
},
|
||||
{
|
||||
"unit": "source/objects/objects",
|
||||
"function": "$L10620",
|
||||
"owner_function": "_attachments_delete",
|
||||
"reason": "the exact owning COMDAT and an internal relocation prove this differently named jump-table label is the same destination"
|
||||
},
|
||||
{
|
||||
"unit": "source/memory/zlib/infblock",
|
||||
"function": "$L2587",
|
||||
"owner_function": "_inflate_blocks",
|
||||
"reason": "the exact owning COMDAT and an internal relocation prove this differently numbered jump-table label is the same destination"
|
||||
},
|
||||
{
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox_vertex_shaders_runtime",
|
||||
"function": "_rasterizer_set_vertex_shader_permutation",
|
||||
"reason": "hardened COFF comparison proves all 1376 padded bytes and all 133 semantic relocations exact; objdiff reports a switch-table/local-label encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/networking/telnet_console",
|
||||
"function": "_process_telnet_client_buffer",
|
||||
"reason": "hardened COFF comparison proves all 496 padded bytes and all 30 semantic relocations exact; objdiff reports a switch-table/local-label encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_playlist_profile_set_game_engine",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_playlist_profile_change_ctf_rules",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_playlist_profile_change_koth_rules",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_playlist_profile_change_slayer_rules",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_playlist_profile_change_oddball_rules",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_playlist_profile_change_racing_rules",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_playlist_profile_change_player_options",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_playlist_profile_change_item_options",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_playlist_profile_initialize_game_engine",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_playlist_profile_initialize_ctf_rules",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_playlist_profile_initialize_koth_rules",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_playlist_profile_initialize_slayer_rules",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_playlist_profile_initialize_oddball_rules",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_playlist_profile_initialize_racing_rules",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_playlist_profile_initialize_player_options",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_playlist_profile_initialize_item_options",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_player_profile_initialize_controller_settings",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_event_handler_functions",
|
||||
"function": "_player_profile_change_controller_settings",
|
||||
"reason": "hardened COFF comparison proves exact bytes and relocation destinations; objdiff reports a local-symbol ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/render/render_contrails",
|
||||
"function": "_render_contrail",
|
||||
"reason": "hardened COFF comparison proves all 1952 padded bytes and all 57 semantic relocations exact (SHA-256 70d28d083222f55ac171cb1aa9676d018fb2bcae9ee54f09facee54755cef5e8); objdiff reports a switch-table/local-label encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/items/weapons",
|
||||
"function": "_weapon_set_state",
|
||||
"reason": "hardened COFF comparison proves all 432 padded bytes and all 21 semantic relocations exact (SHA-256 667efc085661d6b50a6fb3c778be5f3b44e05acfca0132acf3aa527b21f20b74); objdiff reports a switch-table/local-label encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/ai/path_smoothing",
|
||||
"function": "_surface_is_walkable",
|
||||
"reason": "hardened COFF comparison proves all 128 padded bytes and all 5 semantic relocations exact (SHA-256 a58fa4f6cf9598874c2a0d1fb60f226f65dea7f5cbc7182a682b2faefc62580f); the private name is recovered from the source-backed path-smoothing helper cluster"
|
||||
},
|
||||
{
|
||||
"unit": "source/rasterizer/rasterizer_debug",
|
||||
"function": "_rasterizer_debug_line",
|
||||
"reason": "hardened COFF comparison proves all 32 padded bytes and the REL32 relocation to _rasterizer_debug_line_shaded exact (SHA-256 60f8ba4857cfb47aa739f77d4df9844fae5d61fb4292d7d92b25c28166a7a0d7)"
|
||||
},
|
||||
{
|
||||
"unit": "source/rasterizer/rasterizer_debug",
|
||||
"function": "_rasterizer_debug_triangle",
|
||||
"reason": "hardened COFF comparison proves all 32 padded bytes and the REL32 relocation to _rasterizer_debug_triangle_shaded exact (SHA-256 1b0df8cc752bec5820c858223f553d6f62fc7e39bac45bbb9b209d0f980a148a)"
|
||||
},
|
||||
{
|
||||
"unit": "source/cutscene/recorded_animation_playback",
|
||||
"function": "_recorded_animation_apply_event_stream",
|
||||
"reason": "hardened COFF comparison proves all 496 padded bytes and all 34 semantic relocations exact (SHA-256 4e8a5bd6f5b73b358df9e82beed6a1a08aa23ee6f84b353aa3026df37f1b441b); objdiff reports a switch-table/local-label encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/camera/camera_scripting",
|
||||
"function": "_scripted_camera_update",
|
||||
"reason": "hardened COFF comparison proves all 1664 padded bytes and all 82 semantic relocations exact (SHA-256 cb504e5b44213920854f97d593ab2361bda073fcb0ffef531347b0c4b8565e06); objdiff reports a switch-table/local-label encoding false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/game/game_engine_ctf",
|
||||
"function": "_ctf_engine_display_score",
|
||||
"reason": "hardened COFF comparison proves all 928 padded bytes and all 78 semantic relocations exact (SHA-256 df4518d31867315a05039fdcf8679ba2476011eeb70122ac00c6b6efef13f148); objdiff reports a switch-table/local-label ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/game/game_engine_oddball",
|
||||
"function": "_oddball_engine_display_score",
|
||||
"reason": "hardened COFF comparison proves all 736 padded bytes and all 56 semantic relocations exact (SHA-256 6ad4051ea66ca25449fb855b7cb0076efef3e056e80fa1a6566d7dc5fc2a2e38); objdiff reports pooled-string COMDAT ownership as a false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/first_person_weapons",
|
||||
"function": "_first_person_weapon_state_from_weapon_message",
|
||||
"reason": "hardened COFF comparison proves all 192 padded bytes and all 19 semantic relocations exact (SHA-256 f551efe027b59b504571439a15088c0065c23383298acbcdb85aeb04f10d3947); objdiff reports a private switch-table/local-label ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/first_person_weapons",
|
||||
"function": "_first_person_animation_type_from_weapon_state",
|
||||
"reason": "hardened COFF comparison proves all 272 padded bytes and all 25 semantic relocations exact (SHA-256 ea1838b37d9d2a3d39b80a5118d966f264e0daecbff3a47c9f41a6968006b499); objdiff reports a private switch-table/local-label ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/first_person_weapons",
|
||||
"function": "_first_person_weapon_set_state",
|
||||
"reason": "hardened COFF comparison proves all 688 padded bytes and all 26 semantic relocations exact (SHA-256 965964af9115913e36fa06e152828b2e857e7ac59e2cc0e6fdcff29ddebcb91f); objdiff reports a private switch-table/local-label ownership false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_game_data_input_functions",
|
||||
"function": "_mutliplayer_settings_select_list_update_displayed_items",
|
||||
"reason": "hardened COFF comparison proves all 1424 padded bytes and all 73 semantic relocations exact (SHA-256 adce7f9ab32aee72ec9d542efc297df9295a839a27406848eb8467ffea97594f); objdiff reports compiler-local switch-table labels as a false negative; January's original misspelling of multiplayer in the owner name is preserved"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget_game_data_input_functions",
|
||||
"function": "_server_list_menu_update",
|
||||
"reason": "hardened COFF comparison proves all 2016 padded bytes and all 115 semantic relocations exact (SHA-256 f7a5f8c39ab8f6200fa4dfe798c533c40d76e0f8acd06935cea2d5a696c73334); objdiff reports this complete typed server-list graph as a false negative"
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/ui_widget",
|
||||
"function": "_remap_sticks_for_local_player",
|
||||
"reason": "hardened COFF comparison proves all 304 padded bytes and all 31 semantic relocations exact (SHA-256 963b6756ac2f3b70faf18955bad37bac6ed40bbe366baa697feccc61e7050ce8); objdiff reports a control-flow pairing false negative after the natural switch assigns the remapped icon and reaches the shared return"
|
||||
}
|
||||
]
|
||||
@@ -1,68 +0,0 @@
|
||||
[
|
||||
{ "file_offset": 1536, "name" : ".text" },
|
||||
{ "file_offset": 1926336, "name" : "D3D" },
|
||||
{ "file_offset": 2005192, "name" : "D3D_RD" },
|
||||
{ "file_offset": 2011016, "name" : "D3D_RW" },
|
||||
{ "file_offset": 2011136, "name" : "D3D_URW" },
|
||||
{ "file_offset": 2024576, "name" : "D3DX" },
|
||||
{ "file_offset": 2044112, "name" : "D3DX_RD" },
|
||||
{ "file_offset": 2044320, "name" : "DSOUND" },
|
||||
{ "file_offset": 2092088, "name" : "DSOUND_RD" },
|
||||
{ "file_offset": 2171408, "name" : "DSOUND_RW" },
|
||||
{ "file_offset": 2173056, "name" : "DSOUND_URW" },
|
||||
{ "file_offset": 2173248, "name" : "XNET" },
|
||||
{ "file_offset": 2218120, "name" : "XNET_RD" },
|
||||
{ "file_offset": 2218496, "name" : "BINK" },
|
||||
{ "file_offset": 2308672, "name" : "BINK32" },
|
||||
{ "file_offset": 2313408, "name" : "BINK32A" },
|
||||
{ "file_offset": 2318912, "name" : "BINK16" },
|
||||
{ "file_offset": 2323808, "name" : "BINK4444" },
|
||||
{ "file_offset": 2329344, "name" : "BINK5551" },
|
||||
{ "file_offset": 2333760, "name" : "BINK16MX" },
|
||||
{ "file_offset": 2334080, "name" : "BINK16X2" },
|
||||
{ "file_offset": 2335456, "name" : "BINK16M" },
|
||||
{ "file_offset": 2335968, "name" : "BINK32MX" },
|
||||
{ "file_offset": 2336416, "name" : "BINK32X2" },
|
||||
{ "file_offset": 2337856, "name" : "BINK32M" },
|
||||
{ "file_offset": 2338208, "name" : ".XPP$ClassA" },
|
||||
{ "file_offset": 2338212, "name" : ".XPP$ClassHub" },
|
||||
{ "file_offset": 2338216, "name" : ".XPP$ClassMU" },
|
||||
{ "file_offset": 2338220, "name" : ".XPP$ClassXID" },
|
||||
{ "file_offset": 2338228, "name" : ".XPP$ClassZ" },
|
||||
{ "file_offset": 2338232, "name" : ".XPP$Data" },
|
||||
{ "file_offset": 2338948, "name" : ".XPPCINIT" },
|
||||
{ "file_offset": 2342115, "name" : ".XPPCODE" },
|
||||
{ "file_offset": 2370500, "name" : ".XPPRDATA" },
|
||||
{ "file_offset": 2370592, "name" : ".idata$5" },
|
||||
{ "file_offset": 2371276, "name" : ".rdata" },
|
||||
{ "file_offset": 2845216, "name" : ".rdata$debug" },
|
||||
{ "file_offset": 2845312, "name" : ".CRT$RIA" },
|
||||
{ "file_offset": 2845316, "name" : ".CRT$RII10" },
|
||||
{ "file_offset": 2845320, "name" : ".CRT$RII20" },
|
||||
{ "file_offset": 2845324, "name" : ".CRT$RIZ" },
|
||||
{ "file_offset": 2845328, "name" : ".CRT$XCA" },
|
||||
{ "file_offset": 2845332, "name" : ".CRT$XCU" },
|
||||
{ "file_offset": 2845340, "name" : ".CRT$XCZ" },
|
||||
{ "file_offset": 2845344, "name" : ".CRT$XIA" },
|
||||
{ "file_offset": 2845348, "name" : ".CRT$XIC" },
|
||||
{ "file_offset": 2845356, "name" : ".CRT$XIZ" },
|
||||
{ "file_offset": 2845360, "name" : ".CRT$XPA" },
|
||||
{ "file_offset": 2845364, "name" : ".CRT$XPX" },
|
||||
{ "file_offset": 2845368, "name" : ".CRT$XPZ" },
|
||||
{ "file_offset": 2845372, "name" : ".CRT$XTA" },
|
||||
{ "file_offset": 2845376, "name" : ".CRT$XTZ" },
|
||||
{ "file_offset": 2845392, "name" : ".data" },
|
||||
{ "file_offset": 3251360, "name" : ".bss" },
|
||||
{ "file_offset": 6401024, "name" : "DOLBY" },
|
||||
{ "file_offset": 6429088, "name" : "BINKDATA" },
|
||||
{ "file_offset": 6446080, "name" : ".idata$2" },
|
||||
{ "file_offset": 6446120, "name" : ".idata$3" },
|
||||
{ "file_offset": 6446140, "name" : ".idata$4" },
|
||||
{ "file_offset": 6446824, "name" : ".idata$6" },
|
||||
{ "file_offset": 6446848, "name" : ".tls" },
|
||||
{ "file_offset": 6446852, "name" : ".tls$" },
|
||||
{ "file_offset": 6446860, "name" : ".tls$ZZZ" },
|
||||
{ "file_offset": 6446880, "name" : ".XBLD" },
|
||||
{ "file_offset": 6446896, "name" : ".XBLD$A" },
|
||||
{ "file_offset": 6446912, "name" : ".XBLD$V" }
|
||||
]
|
||||
@@ -1,39 +0,0 @@
|
||||
[
|
||||
{
|
||||
"unit": "source/objects/objects",
|
||||
"section": ".bss",
|
||||
"reason": "January layout, PDB-public evidence, and module-local references prove three source-private object globals followed by the externally visible debug byte",
|
||||
"snapshot": {
|
||||
"size": 13,
|
||||
"flags": 3224371328,
|
||||
"relocation_count": 0,
|
||||
"normalized_sha256": "dd46c3eebb1884ff3b5258c0a2fc9398e560a29e0780d4b53869b6254aa46a96",
|
||||
"symbols": [
|
||||
{
|
||||
"name": "_object_name_list",
|
||||
"value": 0,
|
||||
"type": 0,
|
||||
"storage": 3
|
||||
},
|
||||
{
|
||||
"name": "_object_memory_pool",
|
||||
"value": 4,
|
||||
"type": 0,
|
||||
"storage": 3
|
||||
},
|
||||
{
|
||||
"name": "_object_globals",
|
||||
"value": 8,
|
||||
"type": 0,
|
||||
"storage": 3
|
||||
},
|
||||
{
|
||||
"name": "_debug_objects_position_velocity",
|
||||
"value": 12,
|
||||
"type": 0,
|
||||
"storage": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
-23861
File diff suppressed because it is too large.
Load diff
+76
-165
@@ -1,70 +1,22 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# root build script
|
||||
# root build script: writes build.ninja for the native ports (Linux, Windows,
|
||||
# Android)
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import (
|
||||
IO,
|
||||
Any,
|
||||
Callable,
|
||||
Dict,
|
||||
Iterable,
|
||||
List,
|
||||
Optional,
|
||||
Set,
|
||||
Tuple,
|
||||
TypedDict,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
|
||||
from tools.project_x86 import (
|
||||
Object,
|
||||
ObjectStatus,
|
||||
ProjectConfig,
|
||||
SolutionConfig,
|
||||
calculate_progress,
|
||||
generate_build,
|
||||
is_windows,
|
||||
)
|
||||
import io
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
|
||||
from tools import ninja_syntax
|
||||
from tools.android_build import android_configure_inputs, generate_android_build
|
||||
from tools.linux_build import generate_linux_build, linux_configure_inputs
|
||||
from tools.windows_build import generate_windows_build, windows_configure_inputs
|
||||
|
||||
# arguments
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"mode",
|
||||
choices=["configure", "progress"],
|
||||
default="configure",
|
||||
help="script mode (default: configure)",
|
||||
nargs="?",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--objdiff",
|
||||
metavar="BINARY",
|
||||
type=Path,
|
||||
help="path to objdiff-cli binary (optional)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--csplit",
|
||||
metavar="BINARY",
|
||||
type=Path,
|
||||
help="path to csplit binary (optional)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--ninja",
|
||||
metavar="BINARY",
|
||||
type=Path,
|
||||
help="path to ninja binary (optional)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--ml",
|
||||
metavar="BINARY",
|
||||
type=Path,
|
||||
help="path to Microsoft Macro Assembler for authentic CRT .asm units",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--linux-cc",
|
||||
metavar="BINARY",
|
||||
@@ -73,25 +25,25 @@ parser.add_argument(
|
||||
parser.add_argument(
|
||||
"--compiler-launcher",
|
||||
metavar="BINARY",
|
||||
help="native ports: a program that runs each compile, such as ccache "
|
||||
help="a program that runs each compile, such as ccache "
|
||||
"(links and the Android host's few units run the compiler directly)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--release",
|
||||
action="store_true",
|
||||
help="release builds of the native ports (Linux, Windows, Android): assertions are not checked",
|
||||
help="release builds (Linux, Windows, Android): assertions are not checked",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--lto",
|
||||
choices=["full", "thin", "off"],
|
||||
default="full",
|
||||
help="link-time optimisation of the native ports (Linux, Windows): full (the default: the whole game "
|
||||
help="link-time optimisation (Linux, Windows): full (the default: the whole game "
|
||||
"optimised as one module, the fastest code and the slowest links), thin (parallel and incremental) or off",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--portable",
|
||||
action="store_true",
|
||||
help="native x86 ports (Linux, Windows): code for any x86-64 processor (SSE2) rather than for this "
|
||||
help="x86 builds (Linux, Windows): code for any x86-64 processor (SSE2) rather than for this "
|
||||
"machine's (-march=native, the default); use it for builds that run on other computers",
|
||||
)
|
||||
parser.add_argument(
|
||||
@@ -100,7 +52,7 @@ parser.add_argument(
|
||||
const="train",
|
||||
default="use",
|
||||
choices=["use", "train", "off"],
|
||||
help="profile-guided optimisation of the native ports: use (the default) optimises with the profiles in pgo/, "
|
||||
help="profile-guided optimisation: use (the default) optimises with the profiles in pgo/, "
|
||||
"train (or plain --pgo) first records this platform's profile if it is missing, by letting an instrumented "
|
||||
"build play every campaign level (needs the game data in assets/ and a display; Linux and Windows), off does "
|
||||
"without",
|
||||
@@ -109,7 +61,7 @@ parser.add_argument(
|
||||
"--pgo-profile",
|
||||
metavar="PROFDATA",
|
||||
type=Path,
|
||||
help="native ports: profile-guided optimisation from this profile instead",
|
||||
help="profile-guided optimisation from this profile instead",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--android-ndk",
|
||||
@@ -121,114 +73,73 @@ parser.add_argument(
|
||||
type=str,
|
||||
help="clang with the arm64_32 target for the Android guest (default: clang)",
|
||||
)
|
||||
if not is_windows():
|
||||
parser.add_argument(
|
||||
"--wrapper",
|
||||
metavar="BINARY",
|
||||
type=Path,
|
||||
help="path to wibo or wine (optional)",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# path setup
|
||||
# the settings the builds read
|
||||
sln = SimpleNamespace(
|
||||
build_dir=Path("build"),
|
||||
linux_cc=args.linux_cc,
|
||||
compiler_launcher=args.compiler_launcher,
|
||||
port_release=args.release,
|
||||
port_lto=args.lto,
|
||||
port_portable=args.portable,
|
||||
port_pgo=args.pgo,
|
||||
port_pgo_profile=args.pgo_profile,
|
||||
android_ndk=args.android_ndk,
|
||||
android_guest_cc=args.android_guest_cc,
|
||||
)
|
||||
|
||||
build_dir = Path("build")
|
||||
config_dir = Path("config")
|
||||
config_json_path = config_dir / "config.json"
|
||||
project_dir = Path("projects")
|
||||
tools_dir = Path("tools")
|
||||
|
||||
# build config json
|
||||
def is_windows() -> bool:
|
||||
return os.name == "nt"
|
||||
|
||||
class BuildConfigObject(TypedDict):
|
||||
name: str
|
||||
index: int
|
||||
status: str
|
||||
options: Dict[str, Any]
|
||||
|
||||
class BuildConfigProject(TypedDict):
|
||||
name: str
|
||||
guid: str
|
||||
objects: List[BuildConfigObject]
|
||||
options: Dict[str, Any]
|
||||
# build.ninja
|
||||
out = io.StringIO()
|
||||
n = ninja_syntax.Writer(out)
|
||||
n.variable("ninja_required_version", "1.3")
|
||||
n.newline()
|
||||
|
||||
class BuildConfig(TypedDict):
|
||||
name: str
|
||||
guid: str
|
||||
baserom: str
|
||||
projects: List[BuildConfigProject]
|
||||
configure_script = Path(os.path.relpath(os.path.abspath(sys.argv[0])))
|
||||
n.comment("The arguments passed to configure.py, for rerunning it.")
|
||||
n.variable(
|
||||
"configure_args",
|
||||
[f'"{arg}"' if any(ch.isspace() for ch in arg) else arg for arg in sys.argv[1:]],
|
||||
)
|
||||
n.variable("python", f'"{sys.executable}"')
|
||||
n.newline()
|
||||
|
||||
build_config: BuildConfig = json.load(open(config_json_path, "r", encoding="utf-8"))
|
||||
generate_linux_build(n, sln)
|
||||
generate_android_build(n, sln)
|
||||
generate_windows_build(n, sln)
|
||||
|
||||
# solution configuration
|
||||
n.comment("Reconfigure on change")
|
||||
n.rule(
|
||||
name="configure",
|
||||
command=f"$python {configure_script} $configure_args",
|
||||
generator=True,
|
||||
description=f"RUN {configure_script}",
|
||||
)
|
||||
n.build(
|
||||
outputs="build.ninja",
|
||||
rule="configure",
|
||||
implicit=[
|
||||
configure_script,
|
||||
Path("tools/ninja_syntax.py"),
|
||||
*linux_configure_inputs(),
|
||||
*android_configure_inputs(),
|
||||
*windows_configure_inputs(),
|
||||
],
|
||||
)
|
||||
n.newline()
|
||||
|
||||
sln = SolutionConfig()
|
||||
sln.build_dir = build_dir
|
||||
sln.config_dir = config_dir
|
||||
sln.project_dir = project_dir
|
||||
sln.tools_dir = tools_dir
|
||||
# the build for this computer, where it could be generated (the Windows
|
||||
# build is left out when SDL cannot be fetched, for instance)
|
||||
default = "windows" if is_windows() else "linux"
|
||||
if f"\nbuild {default}: " in out.getvalue():
|
||||
n.comment("Default rule: the build for this computer")
|
||||
n.default(default)
|
||||
|
||||
sln.name = build_config["name"]
|
||||
sln.guid = build_config["guid"]
|
||||
sln.baserom = build_config["baserom"]
|
||||
|
||||
# Apply arguments
|
||||
sln.objdiff_path = args.objdiff
|
||||
sln.csplit_path = args.csplit
|
||||
sln.ninja_path = args.ninja
|
||||
sln.ml_path = args.ml
|
||||
sln.linux_cc = args.linux_cc
|
||||
sln.compiler_launcher = args.compiler_launcher
|
||||
sln.port_release = args.release
|
||||
sln.port_lto = args.lto
|
||||
sln.port_portable = args.portable
|
||||
sln.port_pgo = args.pgo
|
||||
sln.port_pgo_profile = args.pgo_profile
|
||||
sln.android_ndk = args.android_ndk
|
||||
sln.android_guest_cc = args.android_guest_cc
|
||||
if not is_windows():
|
||||
sln.wrapper = args.wrapper
|
||||
|
||||
# Tool versions
|
||||
sln.objdiff_tag = "v3.6.0"
|
||||
sln.csplit_tag = "v0.0.2"
|
||||
# v0.0.2 plus upstream's "Fix uninit phony section"; built from source on Linux
|
||||
sln.csplit_source_commit = "db510e7ef9f60bb09b13a3df88c7419e9b215cde"
|
||||
sln.wibo_tag = "1.0.0"
|
||||
sln.uasm_tag = "v2.57r"
|
||||
|
||||
sln.projects = []
|
||||
for build_project in build_config["projects"]:
|
||||
project = ProjectConfig(**build_project.get("options", {}))
|
||||
project.name = build_project["name"]
|
||||
project.guid = build_project["guid"]
|
||||
project.objects = []
|
||||
for build_object in build_project["objects"]:
|
||||
def get_object_completed(status: str) -> ObjectStatus:
|
||||
if status == "MISSING":
|
||||
return ObjectStatus.Missing
|
||||
elif status == "Matching":
|
||||
return ObjectStatus.Matching
|
||||
elif status == "NonMatching":
|
||||
return ObjectStatus.NonMatching
|
||||
assert False, f"Invalid object status {status}"
|
||||
project.objects.append(Object(get_object_completed(build_object["status"]), Path(build_object["name"]), **build_object.get("options", {})))
|
||||
sln.projects.append(project)
|
||||
|
||||
# build file generation
|
||||
|
||||
if args.mode == "configure":
|
||||
if sln.matching and any(
|
||||
obj["status"] != "MISSING" and obj["name"].startswith("libs/d3d8/")
|
||||
for project in build_config["projects"]
|
||||
for obj in project["objects"]
|
||||
):
|
||||
subprocess.run([sys.executable, "libs/d3d8/generate_sdk_overlay.py"], check=True)
|
||||
# Write build.ninja and objdiff.json
|
||||
generate_build(sln)
|
||||
elif args.mode == "progress":
|
||||
# Print progress information
|
||||
calculate_progress(sln)
|
||||
else:
|
||||
sys.exit("Unknown mode: " + args.mode)
|
||||
with open("build.ninja", "w", encoding="utf-8") as f:
|
||||
f.write(out.getvalue())
|
||||
out.close()
|
||||
@@ -1,106 +0,0 @@
|
||||
# Assertions, warnings, and halts: shared API and January matching
|
||||
|
||||
The owner is [source/cseries/cseries.h](../source/cseries/cseries.h).
|
||||
All assertions express a condition that **must be true**. A false condition
|
||||
reports the diagnostic with `display_assert(..., TRUE)` and then calls
|
||||
`system_exit(-1)`. Evaluate diagnostic expressions only on the failure path.
|
||||
|
||||
Warnings likewise report only when their condition is false, but use
|
||||
`display_assert(..., FALSE)` and **continue**. Halts are unconditional: they
|
||||
report with `TRUE` and call the existing `halt_and_catch_fire()` owner.
|
||||
They do not take an assertion condition.
|
||||
|
||||
| Intent | Current supported API | Diagnostic |
|
||||
| --- | --- | --- |
|
||||
| Plain assertion | `assert(expression)` | Stringified expression |
|
||||
| Diagnostic assertion | `dassert(expression, diagnostic)` | Supplied string expression |
|
||||
| Formatted assertion | `vassert(expression, csprintf(temporary, format, ...))` | Formatted string, produced only on failure |
|
||||
| Preserve original source location | `match_assert(file, line, expression)` | Stringified expression |
|
||||
| Preserve location and diagnostic | `match_dassert(file, line, expression, diagnostic)` | Supplied string expression |
|
||||
| Preserve location and formatted diagnostic | `match_vassert(file, line, expression, csprintf(temporary, format, ...))` | Formatted string |
|
||||
| Plain warning | `warn(expression)` | Stringified expression; nonfatal |
|
||||
| Diagnostic warning | `dwarn(expression, diagnostic)` | Supplied string; nonfatal |
|
||||
| Formatted warning | `vwarn(expression, csprintf(temporary, format, ...))` | Failure-only formatting; nonfatal |
|
||||
| Plain halt | `halt()` | No message; unconditional fatal report |
|
||||
| Diagnostic halt | `dhalt(diagnostic)` | Supplied string; unconditional |
|
||||
| Formatted halt | `vhalt(csprintf(temporary, format, ...))` | Formatted string; unconditional |
|
||||
|
||||
Warnings and halts also have `match_warn`, `match_dwarn`, `match_vwarn`,
|
||||
`match_halt`, `match_dhalt`, and `match_vhalt` counterparts. Their first two
|
||||
arguments are the original `file` and `line`, followed by the ordinary API's
|
||||
arguments.
|
||||
|
||||
`vassert`/`match_vassert` already accepted a message expression before this
|
||||
cleanup. The `dassert`/`dwarn`/`dhalt` names and matching counterparts are
|
||||
statement-safe diagnostic convenience wrappers for the existing behavior,
|
||||
not a claim that these exact wrappers were in Bungie's January source.
|
||||
Existing callers remain compatible.
|
||||
|
||||
The pinned XDK 3911 compiler is VC7 13.00.9254.1. Its preprocessor rejects
|
||||
`#define vassert(expression, format, ...)` with C2010, and does not implement
|
||||
`__VA_ARGS__`. Variadic **functions** such as `csprintf` are supported. Do not
|
||||
change compiler versions, add a function-call wrapper, or force inline code
|
||||
merely to obtain the newer comma-separated macro syntax.
|
||||
|
||||
The supplied CE reference files themselves use two-argument
|
||||
`vassert(expression, message)` calls: `random_math.c`'s random-seed lock
|
||||
checks, server line 1248, and client line 521. These calls corroborate the
|
||||
older API, but the attachments do not include its defining `cseries.h`.
|
||||
See [the source reconstruction map](user_source_reconstruction_map_20260906.md).
|
||||
|
||||
## Units example: assert the invariant, not the error condition
|
||||
|
||||
The invariant is that an inventory weapon being dropped is **not** connected
|
||||
to the map:
|
||||
|
||||
```c
|
||||
match_vassert(
|
||||
"c:\\halo\\SOURCE\\units\\units.c",
|
||||
8505,
|
||||
!TEST_FLAG(weapon->object.flags, _object_connected_to_map_bit),
|
||||
csprintf(
|
||||
temporary,
|
||||
"a %s tried to drop a %s which was connected to the map.",
|
||||
tag_get_name(unit->definition_index),
|
||||
tag_get_name(weapon->definition_index)));
|
||||
```
|
||||
|
||||
Omitting `!` reverses the behavior: it would assert for a disconnected weapon
|
||||
and accept the connected weapon. Keep the two `tag_get_name` calls and the
|
||||
formatting inside the assertion message expression, so successful execution
|
||||
does not evaluate them.
|
||||
|
||||
The matching form retains January's original filename and line number. In a
|
||||
`NON_MATCHING` build, `MATCH_FILE`/`MATCH_LINE` deliberately use the actual
|
||||
current source location instead. For new code with no original location to
|
||||
preserve, use the ordinary `assert`/`dassert`/`vassert` form.
|
||||
|
||||
## Limits and adoption
|
||||
|
||||
- Use braces around surrounding `if`/`else` branches. Some inherited macros
|
||||
expand to an `if` statement; an unbraced outer `else` can bind incorrectly.
|
||||
- Keep expressions free of unnecessary side effects. The condition is
|
||||
evaluated once, and the diagnostic only on failure, but argument evaluation
|
||||
order inside a formatted call remains the C compiler's responsibility.
|
||||
- `temporary` is the existing shared 256-byte buffer and `csprintf` uses
|
||||
unbounded `vsprintf`. Preserve authenticated legacy call sites; this is not
|
||||
a thread-safe or size-safe general logging facility. Do not pass arbitrary
|
||||
unbounded input or preformat into this buffer on the success path.
|
||||
- Do not add `NDEBUG`-based removal: the current project macros do not have
|
||||
that contract. Both debug and `NDEBUG` fixture builds are tested.
|
||||
- Migrate one coherent owner at a time and run its strict gate plus consumer
|
||||
regression checks. Do not bulk-rewrite active lanes or lose original
|
||||
diagnostic text, argument types, failure polarity, or source locations.
|
||||
|
||||
The executable macro tests are
|
||||
[tools/test_cseries_assertions.py](../tools/test_cseries_assertions.py), using
|
||||
[C fixtures](../tools/fixtures/cseries_assertions.c) compiled by the actual VC7
|
||||
toolchain. They check success/failure, lazy formatting, single evaluation,
|
||||
exact matching/nonmatching locations, fatal flag and `system_exit(-1)` or
|
||||
`halt_and_catch_fire()` dispatch, nonfatal warning continuation, and
|
||||
connected-weapon polarity. They use bounded diagnostic API doubles; they do
|
||||
not validate the termination implementation, `vsprintf` buffer safety, or the
|
||||
game's complete error-reporting subsystem.
|
||||
|
||||
See also [common constants](common_constants.md) and the
|
||||
[Units cleanup ledger](object_matching_logs/units_obj_assertion_cleanup_20260906.md).
|
||||
@@ -1,81 +0,0 @@
|
||||
# Campaign house rules and working cadence
|
||||
|
||||
User-confirmed 2026-09-07. Apply these to reconciliation and new reconstruction.
|
||||
|
||||
1. Put a no-argument `void` on its own line inside the parameter list.
|
||||
2. Put each parameter on its own line.
|
||||
3. Use explicit returns: `return;` for void functions, an appropriate returned
|
||||
value for non-void functions. Do not add an invalid bare return to non-void C.
|
||||
4. Use subsystem typed macros wrapping `tag_get`.
|
||||
5. Use typed object-access macros instead of repeated raw-access casts.
|
||||
6. Preserve January's inline schedule; do not emit a `point_from_line3d` COMDAT.
|
||||
7. Give private functions authentic or descriptive project-style names, never
|
||||
`code` plus an address.
|
||||
8. Likewise name globals; do not add `bss` plus address identifiers.
|
||||
9. Put prototypes in their genuine owners, not unrelated consumer C files.
|
||||
10. Helper/math functions may use inline assembly sparingly, with evidence.
|
||||
11. If easy exactness fails, retain credible fuzzy code, document it and park.
|
||||
12. Prioritize small objects in substantially reconstructed families.
|
||||
13. Avoid manual/forced inlining; retain ordinary helpers and natural scheduling.
|
||||
14. Use open-source Marathon as a style/semantic reference, not January byte proof.
|
||||
15. When no dedicated header exists, use the closest genuine associated header.
|
||||
16. Use correct enum constants in switch tables.
|
||||
17. Combine declaration and initialization when practical.
|
||||
18. Prefer suitable `cseries.h` macros over manual bit manipulation.
|
||||
19. Use project types, e.g. `real`, rather than generic replacements.
|
||||
20. Reject fake matching and source implausible for the original program.
|
||||
21. Reject nonsensical logic even when bytes happen to match.
|
||||
22. Use `/QIfist` where required by the target/compiler evidence. It is a
|
||||
per-TU option, not a blanket default or license to change unrelated flags.
|
||||
Check the complete TU and affected callers; conversion instructions and
|
||||
widths must agree. Existing usage is recorded in `config/config.json`.
|
||||
|
||||
Rule 6 has a later, narrow owner-approved exception for folded header-inline
|
||||
helpers (see `docs/object_matching_logs/claude_lane_b_HANDOFF_20260920.md`,
|
||||
section 3). A translation unit may emit a shared-header `__inline` COMDAT,
|
||||
including `_point_from_line3d`, only when the emitted copy is byte-identical
|
||||
to January's selected copy, its caller is strictly exact, the full ownership
|
||||
and build sweep has zero regressions, and the selected-provider link passes.
|
||||
January's per-object folded survivor is not an absolute emission boundary.
|
||||
Do not hand-expand or hand-copy the helper to evade this check.
|
||||
|
||||
## Batch workflow
|
||||
|
||||
Reconcile coherent multi-object or owner/family packets, normally several
|
||||
thousand bytes when available. Review source quality, headers, ABI and emitted
|
||||
ownership together; run one full build, tools suite and stable regression sweep
|
||||
per batch. Use existing strict gates for ordinary exact leaves. Reserve new
|
||||
bespoke runtime harnesses for ambiguous behavior/ABIs, not every tiny function.
|
||||
Isolate blockers without holding unrelated admissible work. Preserve donor trees.
|
||||
|
||||
Publish only verified source/tooling gains to canonical and the authorized
|
||||
GitHub branches. Donor-relative headline totals are not additive canonical
|
||||
credit. Keep meaningful exact bytes distinct from padded and fuzzy counts.
|
||||
|
||||
User clarification, 2026-09-07: preserve the best available house-rule-compliant
|
||||
Claude implementations in canonical and GitHub even when non-exact. Document
|
||||
the donor, fresh measurements, remaining differences and research pointers;
|
||||
do not leave useful fuzzy work stranded in donor trees. Closeness never
|
||||
justifies undefined/nonsensical logic or inappropriate Matching credit.
|
||||
Any accepted loss of exactness must be explicitly recorded and subtracted,
|
||||
not hidden behind the batch's gross gains or a semantic-match override.
|
||||
|
||||
Refresh the canonical treemap after each **10,000 additional verified reconciled
|
||||
meaningful code bytes**. Starting checkpoint for this cadence is **930,828**;
|
||||
the first threshold is **940,828**. Record the next threshold in the queue.
|
||||
Do not start a timer or unrelated recurring automation for this work threshold.
|
||||
|
||||
## Quick references
|
||||
|
||||
- [Constants, types, flags and representations](common_constants.md)
|
||||
- [Assertions, warnings and halts](assertions.md): predicates express required
|
||||
invariants; diagnostics are lazy. The weapon example needs `!TEST_FLAG(...)`.
|
||||
VC7 uses a formatted message expression, not modern variadic macros.
|
||||
- [Supplied-source reconstruction map](user_source_reconstruction_map_20260906.md)
|
||||
- [Matching methodology](matching_methodology.md)
|
||||
- [Reconciliation queue](reconciliation_queue_20260907.md)
|
||||
|
||||
Cross-build symbols/types are evidence, not interchangeable January layouts.
|
||||
Analyze supplied executables as data; do not execute them. Preserve binaries
|
||||
and private symbol assets locally, outside published source batches. Inlined
|
||||
source and absent debug assets cannot be recovered automatically with certainty.
|
||||
@@ -1,631 +0,0 @@
|
||||
# CLAUDE LANE A — AI Core Exact-Match Closeout (79,657 Remaining Halo Bytes)
|
||||
|
||||
You are continuing the Halo January 14, 2002 Xbox exact-match campaign. Your job is to maximize verified, source-authentic strict matches within one isolated AI-core portfolio while producing house-rule-clean fuzzy reconstructions for genuinely unresolved functions.
|
||||
|
||||
## 1. Frozen baseline and isolation
|
||||
|
||||
Use exactly this baseline:
|
||||
|
||||
- Commit: `6130661c9585fdb2785b3ff6bdb2ad0cfef0520c`
|
||||
- Branch represented by the baseline: `jonas/exact-pilots`
|
||||
|
||||
Create a new isolated Git worktree and branch from that exact commit, for example:
|
||||
|
||||
- Worktree: `C:\halo-worktrees\claude-lane-a-ai-core-20260920`
|
||||
- Branch: `claude/lane-a-ai-core-20260920`
|
||||
|
||||
Before doing any work:
|
||||
|
||||
1. Verify `git rev-parse HEAD` equals the full baseline hash.
|
||||
2. Verify `git status --short` is empty.
|
||||
3. Do not use a newer or older canonical checkout as the source of truth.
|
||||
4. Do not mutate the canonical checkout.
|
||||
5. Do not push anything.
|
||||
6. Do not rebase, merge, pull, or incorporate another active lane.
|
||||
7. Do not copy complete files from stale worktrees. Historical worktrees and branches are evidence sources only.
|
||||
8. Keep every experiment in this lane or under `scratch/`.
|
||||
9. At completion, leave the lane committed and clean.
|
||||
|
||||
Expected baseline sanity figures are approximately:
|
||||
|
||||
- Halo accepted: `7,291 / 7,574` functions
|
||||
- Halo accepted meaningful bytes: `1,443,979 / 1,770,166`
|
||||
- Overall accepted: `7,558` functions / `1,465,211` meaningful bytes
|
||||
- Parks: `184 active / 0 stale / 0 invalid`
|
||||
|
||||
Recompute these figures from the baseline rather than blindly trusting them. Stop and diagnose if the baseline materially differs.
|
||||
|
||||
## 2. Exclusive production scope
|
||||
|
||||
You may edit only these 11 production C translation units:
|
||||
|
||||
1. `source/ai/actor_firing_position.c` — 1,113 remaining meaningful bytes
|
||||
2. `source/ai/actor_looking.c` — 5,316
|
||||
3. `source/ai/actor_moving.c` — 10,402
|
||||
4. `source/ai/actor_perception.c` — 17,272
|
||||
5. `source/ai/actors.c` — 4,308
|
||||
6. `source/ai/ai.c` — 2,253
|
||||
7. `source/ai/ai_communication.c` — 11,377
|
||||
8. `source/ai/ai_debug.c` — 26,513
|
||||
9. `source/ai/ai_script.c` — 214
|
||||
10. `source/ai/encounters.c` — 745
|
||||
11. `source/ai/props.c` — 144
|
||||
|
||||
Frozen portfolio total: **79,657 remaining Halo meaningful bytes**.
|
||||
|
||||
This number is the starting residual portfolio, not earned credit. Re-measure it on the frozen baseline and disclose any difference.
|
||||
|
||||
Do not edit any other `.c`, `.cpp`, `.h`, `.hpp`, `.inl`, or assembly source file. In particular:
|
||||
|
||||
- No Xbox library or vendor-library work.
|
||||
- No unrelated Halo unit.
|
||||
- No shared-header edits.
|
||||
- No generated-source edits.
|
||||
- No compiler, comparator, split-target, object, or build-tool modification.
|
||||
|
||||
Documentation under `docs/object_matching_logs/`, evidence under `scratch/`, and narrowly justified configuration edits described below are allowed.
|
||||
|
||||
If a candidate requires a header correction, do not put a surrogate prototype in the consumer C file and do not edit the header in this lane. Record:
|
||||
|
||||
- the genuine owner header;
|
||||
- every consumer;
|
||||
- the proposed declaration;
|
||||
- the exact function expected to benefit;
|
||||
- the baseline controls;
|
||||
- a minimal deferred patch or edit description;
|
||||
- the evidence needed for a later header-owner lane.
|
||||
|
||||
Then continue elsewhere. A header prerequisite must not stall the portfolio.
|
||||
|
||||
## 3. Goal and work order
|
||||
|
||||
The goal is not “try a few promising functions.” Work the entire allowed portfolio in descending leverage until every remaining owner has one of these dispositions:
|
||||
|
||||
- strict exact and admitted;
|
||||
- credible improved fuzzy source retained at zero credit;
|
||||
- unchanged because the current source remains best;
|
||||
- blocked with a concrete, evidence-specific reopening condition.
|
||||
|
||||
Start with the small units to bank inexpensive closures and validate your workflow:
|
||||
|
||||
1. `props`
|
||||
2. `ai_script`
|
||||
3. `encounters`
|
||||
4. `actor_firing_position`
|
||||
5. `ai`
|
||||
6. `actors`
|
||||
|
||||
Then work:
|
||||
|
||||
7. `actor_looking`
|
||||
8. `actor_moving`
|
||||
9. `ai_communication`
|
||||
10. `actor_perception`
|
||||
11. `ai_debug`
|
||||
|
||||
You may reorder the last five when primary evidence makes another sequence more efficient. Do not spend an entire campaign fighting one allocator/x87 tie while untouched structural or unwritten work remains.
|
||||
|
||||
An old park or rejection is not proof of impossibility. It is binding evidence about hypotheses already tested. Reopen only when you have a genuinely new witness, mechanism, compiler-context fact, source graph, type, owner, ABI, call graph, constant, or cross-build correspondence. Do not repeat rejected spelling searches under new filenames.
|
||||
|
||||
## 4. Required reading before editing
|
||||
|
||||
Read these completely before production edits:
|
||||
|
||||
- `docs/campaign_house_rules.md`
|
||||
- `docs/common_constants.md`
|
||||
- `docs/assertions.md`
|
||||
- `docs/matching_methodology.md`
|
||||
- `docs/campaign_throughput_lessons.md`
|
||||
- `docs/user_source_reconstruction_map_20260906.md`
|
||||
- `tools/campaign/README.md`
|
||||
- `docs/object_matching_logs/astra_90pct_HANDOFF_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_admission_manifest_20260920.json`
|
||||
- `docs/object_matching_logs/astra_90pct_research_atlas_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_rejected_hypotheses_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_context_packet_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_debug_packet_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_canonical_reconciliation_20260920.md`
|
||||
|
||||
Read the relevant unit-specific evidence before assigning each unit:
|
||||
|
||||
### Actor looking
|
||||
|
||||
- `docs/object_matching_logs/actor_looking_obj_evidence_closeout_20260919.md`
|
||||
- `docs/object_matching_logs/astra_90pct_actor_looking_packet_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_research10_actor_looking_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_research10_actor_looking_independent_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_research14_aiming_blockage_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_research14_aiming_blockage_independent_20260920.md`
|
||||
|
||||
### Actor moving
|
||||
|
||||
- `docs/object_matching_logs/astra_90pct_actor_moving_avoidance_packet_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_research8_actor_moving_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_research11_actor_move_update_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_research11_biped_moving_20260920.md`
|
||||
|
||||
### Actor perception
|
||||
|
||||
- `docs/object_matching_logs/astra_90pct_actor_perception_packet_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_research10_perception_refresh_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_research12_perception_update_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_wave2_perception_independent_review_20260920.md`
|
||||
|
||||
### AI communication
|
||||
|
||||
- `docs/object_matching_logs/astra_90pct_research10_communication_event_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_research10_communication_independent_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_research18_communication_probe_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_research18_communication_private_owner_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_communication_independent_review_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_wave4_communication_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_wave4_communication_independent_review_20260920.md`
|
||||
|
||||
### AI debug
|
||||
|
||||
- `docs/object_matching_logs/astra_90pct_wave2_ai_debug_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_wave2_ai_debug_independent_review_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_research12_ai_debug_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_research12_ai_debug_color_independent_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_research12_ai_debug_length_independent_20260920.md`
|
||||
|
||||
Also search `docs/object_matching_logs/` for every allowed object and read its newest reports plus any report named by their “read first,” “prior work,” or “reopening” sections.
|
||||
|
||||
## 5. Evidence sources and authority
|
||||
|
||||
Evidence priority is:
|
||||
|
||||
1. January split object code, padding, relocations, owner topology, target data, and actual executable instructions.
|
||||
2. Authenticated January PDB publics, MAP/public names, strings, and image identities.
|
||||
3. Original Bungie source, symbols, headers, or same-era builds when provenance is established.
|
||||
4. Ghidra and DIA evidence from authenticated supplied builds.
|
||||
5. Earlier/later Halo cross-builds, HCEA, the supplied 2020 symbol executable, and open-source Marathon as corroboration.
|
||||
6. Historical branches and old candidates as hypotheses only.
|
||||
|
||||
Useful local assets include:
|
||||
|
||||
- `C:\Users\isabe\Downloads\Halo Combat Evolved (Jan 14, 2002 prototype)\cachebeta.xbe`
|
||||
- `C:\Users\isabe\Downloads\Halo Combat Evolved (Jan 14, 2002 prototype)\cachebeta.exe`
|
||||
- `C:\Users\isabe\Downloads\Halo Combat Evolved (Jan 14, 2002 prototype)\cachebeta.pdb`
|
||||
- `C:\Users\isabe\Downloads\haloleak2024\halo1\h1_tags\halo_cache_symbols.exe`
|
||||
- `C:\Users\isabe\Downloads\Halo - Combat Evolved (Oct 12, 2001 prototype)\Halo 2276`
|
||||
- `C:\Users\isabe\Documents\Codex\2026-09-20\files-pasted-by-the-user-halo\outputs`
|
||||
- the local Marathon research tree referenced by the campaign documentation.
|
||||
|
||||
Known evidence limits:
|
||||
|
||||
- The January PDB has publics/compiland information but no useful Halo locals, lexical blocks, source lines, or original headers.
|
||||
- The supplied 2020 executable was built with a different compiler and contains confirmed source differences. Its RTC locals, call graphs, assertions, and structural correspondences are corroborating evidence, not automatic January source proof.
|
||||
- HCEA supplies useful types, names, and line information, but it is a different platform/build.
|
||||
- IDA Free 9.4 has no callable automation endpoint here. Do not stall or ask again for one.
|
||||
- Ghidra and DIA are available and authorized.
|
||||
- No additional local full-symbol January build or original Halo source/header archive exists. Do not waste time repeatedly searching for byte-identical copies or asking for nonexistent artifacts.
|
||||
- Decompiler output is reconstructed pseudocode, never original source text.
|
||||
|
||||
Use multiple independent lenses whenever possible: target disassembly, relocation identity, call graph, PDB/MAP identity, cross-build raw instructions, HCEA types, historical compiler behavior, and exact sibling controls.
|
||||
|
||||
## 6. Evidence-backed mechanisms to prioritize
|
||||
|
||||
Astra already established useful, bounded source mechanisms. Use them precisely; do not generalize them beyond their evidence.
|
||||
|
||||
### Actor looking
|
||||
|
||||
The authenticated fuzzy reconstruction establishes:
|
||||
|
||||
- `real look_delta_deviations[2]` and the corresponding private parameter type;
|
||||
- two independently evaluated priority equalities rather than copying the first Boolean result;
|
||||
- the initial `succeeded = FALSE`;
|
||||
- clearing free/optional facing states before installing primary facing.
|
||||
|
||||
The remaining barrier is a concrete stack/register lifetime cascade involving `facing_locked`, `aiming_cosine`, `primary_priority`, the secondary aim-valid result, and desired-facing pointer lifetime. Research authentic owner types, scopes, call-return use, or natural same-compiler donor patterns for this boundary. Do not repeat the already exhausted generic scope/order, stationary-copy, representation-cast, or spelling permutations.
|
||||
|
||||
### Actor moving
|
||||
|
||||
The avoidance packet authenticates array widths, typed aggregate identities, ray/fraction/point families, the transform operation, and several real control facts. The unresolved issue is the genuine January helper/include/inlining mechanism and remaining register lifetime, not a license to emit an unauthorized `point_from_line3d` owner. Seek authentic macro/helper definitions, same-compiler donor call sites, or owner/include evidence. Do not repeat the historical helper-storage-class, force-inline, short-local, clear-first, PIN/MAX, cross-product, or generic flag searches without new evidence.
|
||||
|
||||
### Actor perception
|
||||
|
||||
The authenticated fuzzy patch establishes:
|
||||
|
||||
- one `interesting_orphan_index`;
|
||||
- repeated inner danger predicates that are redundant semantically but supported by original control-flow evidence.
|
||||
|
||||
It fixes the timer and tail structural regions while retaining zero credit. Remaining barriers are a precise call-return scheduling boundary and x87 ordering around squared 2D distance. Seek an authentic helper definition, call-site type context, or natural same-compiler donor. Do not repeat declaration splits, generic scope changes, header-COMDAT distance helpers, or scalar spelling searches already shown inert.
|
||||
|
||||
### AI communication
|
||||
|
||||
The existing packets authenticate much of the possibility-array structure, narrow private types, conversation ownership, and several call relationships. Reconcile the new original private-owner evidence before trying new body shapes. The event residual still has concrete relocation-count differences in actor data, datum access, race lookup, team communication, and low-priority rating paths. Use those relocation multiplicities and January call order as a semantic source-graph diagnostic. Do not count frame equality or later-build store order as exact progress.
|
||||
|
||||
### AI debug
|
||||
|
||||
The best authenticated fuzzy body restores:
|
||||
|
||||
- the fifth activation-marker point;
|
||||
- the vision-cone zero-vector/accumulation graph;
|
||||
- January’s target extent and relocation count.
|
||||
|
||||
Its remaining differences are allocation/scheduling and possibly still-unrecovered scalar lifetimes. Use the 94 protected-local records and direct January references as lower-bound lifetime evidence only. Do not infer complete lifetimes, lexical scopes, or 72/80-byte buffer extents from RTC records alone. Preserve the inherited genuine `point_from_line3d` ownership exactly; do not add, remove, or duplicate it casually.
|
||||
|
||||
### Small AI units
|
||||
|
||||
For the six small units, prioritize:
|
||||
|
||||
- unwritten or placeholder bodies;
|
||||
- authentic private names from January/HCEA/MAP evidence;
|
||||
- wrong scalar widths or enum types;
|
||||
- missing calls and relocation multiplicity;
|
||||
- genuine control-flow topology;
|
||||
- incorrect owner/linkage;
|
||||
- wrong constants already catalogued in `docs/common_constants.md`;
|
||||
- historical best source that was never reconciled onto this baseline.
|
||||
|
||||
Do not assume “small residual” means an allocator tie. Inspect the raw function and relocations first.
|
||||
|
||||
## 7. Complete house rules
|
||||
|
||||
Apply all of these to every retained source change:
|
||||
|
||||
1. Format a no-argument parameter list with `void` on its own line inside the parentheses.
|
||||
2. Put every parameter on its own line.
|
||||
3. End every function, including `void` functions, with an explicit valid `return;`; non-void functions must return an appropriate value.
|
||||
4. Use subsystem typed macros wrapping `tag_get` for typed tag access.
|
||||
5. Use typed object-access macros rather than repeated casts after raw `object_get`.
|
||||
6. Preserve January’s inline schedule. Do not introduce an unauthorized `point_from_line3d` COMDAT or alter its selected owner.
|
||||
7. Name private functions authentically when evidence exists; otherwise use a credible project-style descriptive name. Never add `code_XXXXXXXX` or address-based names.
|
||||
8. Name globals authentically or descriptively according to project conventions. Never add `bss_XXXXXXXX` names.
|
||||
9. Put function prototypes in their genuine owner. Never hide a missing owner declaration in an unrelated consumer C file.
|
||||
10. Helper and math functions may use inline assembly only sparingly and only with function-specific machine-code evidence that C cannot reproduce naturally.
|
||||
11. If exact matching is not readily achievable, retain only credible source-authentic fuzzy progress, document it, give it zero exact credit, and park it with a concrete reopening condition.
|
||||
12. Prefer small objects and high-confidence closures before prolonged allocator fights.
|
||||
13. Avoid manual or forced inlining. Preserve ordinary helpers and natural compiler scheduling.
|
||||
14. Use open-source Marathon only as a semantic/style reference, never as January byte proof.
|
||||
15. If a C file lacks a dedicated header, use the closest genuine associated owner header. Since headers are outside this lane’s write scope, document the needed owner change rather than creating a local facade.
|
||||
16. Use correct named enum constants in switch tables and comparisons.
|
||||
17. Declare and initialize variables together when natural and consistent with genuine source lifetime.
|
||||
18. Prefer established `cseries.h` macros over manual flag and bit manipulation.
|
||||
19. Use project-defined types such as `real`, `boolean`, `byte`, `short`, and `long`, not generic substitutes such as `float`, `bool`, or fixed-width types unless the project itself requires them.
|
||||
20. Reject fake matching and source forms that almost certainly were not present in the original.
|
||||
21. Reject nonsensical logic even if it happens to byte-match.
|
||||
22. Use `/QIfist` only when target/compiler evidence requires it, only for the relevant TU, and only after checking every function and caller affected by that option.
|
||||
23. Use the correct `assert`, `dassert`, `vassert`, `warn`, `dwarn`, `vwarn`, `halt`, `dhalt`, and `vhalt` family contracts. Assertion predicates describe the required true invariant. Diagnostics must remain lazy. Do not manually expand one into `display_assert`/`system_exit` merely to shape bytes.
|
||||
24. Preserve authentic January bugs only when direct evidence proves them. Mark them with a precise `BUG:` comment where project policy requires it. Do not invent undefined behavior, uninitialized reads, overflows, invalid aliasing, or out-of-bounds access to steer code generation.
|
||||
25. A strict match does not excuse implausible source. Equality is necessary but not sufficient for admission.
|
||||
26. Do not add dead locals, redundant stores, duplicate calls, empty branches, goto-next-label constructs, self-assignments, volatile reinterpretation, arbitrary union punning, raw-byte emission, linker tricks, or code-generation pragmas unless independent evidence authenticates that exact construct.
|
||||
27. Do not use manual machine bytes or edit target objects.
|
||||
28. Do not change the comparator, normalization rules, semantic-credit policy, or acceptance thresholds.
|
||||
29. Do not trade away an inherited exact function for a larger gross gain.
|
||||
30. Preserve code, data, BSS/COMMON, relocation, linkage, COMDAT, and selected-owner topology.
|
||||
31. Correct fuzzy code gets zero exact credit. Never call 100% diagnostic similarity strict exact unless the strict comparator and ownership checks agree.
|
||||
32. Function exactness and whole-object completion are separate claims. Do not mark an object complete until all target owners, data, selected providers, extra owners, and veto conditions have been audited.
|
||||
33. Do not count external Xbox/vendor code toward this Halo lane.
|
||||
34. Do not count already-exact baseline work, embedded labels, alias duplicates, documentation, configuration edits, or repeated historical work as new bytes.
|
||||
35. Do not fabricate original names. A unique byte match from `namegap.py` is a proposal, not name provenance.
|
||||
|
||||
## 8. Parallel worker architecture
|
||||
|
||||
Use subagents aggressively, but keep their responsibilities disjoint.
|
||||
|
||||
Recommended structure:
|
||||
|
||||
- One worker per C file, or one worker for each small-file group with no overlapping file.
|
||||
- Dedicated research workers may inspect evidence for actor looking, moving, perception, communication, and debug.
|
||||
- Workers may read anything but may write only scratch candidates and reports.
|
||||
- Workers must not run Ninja, edit shared configuration, commit, push, or land directly in production.
|
||||
- Workers compile with `tools/campaign/gate.py` into PID-specific scratch objects.
|
||||
- The orchestrator independently reviews and lands minimal patches.
|
||||
- Every landed function receives a separate adversarial review by a worker that did not author it.
|
||||
- Do not let multiple workers edit the same production file.
|
||||
- Do not let workers change build outputs used by another worker.
|
||||
|
||||
Each worker brief must include:
|
||||
|
||||
- exact baseline commit;
|
||||
- exact owned C file;
|
||||
- current exact/residual/unwritten census;
|
||||
- existing parks and prior rejected hypotheses;
|
||||
- mandatory evidence files;
|
||||
- house rules;
|
||||
- required before/after gate;
|
||||
- owner/data/COMMON/point guard;
|
||||
- prohibition on production/config/header edits;
|
||||
- exact/fuzzy accounting rules.
|
||||
|
||||
## 9. Baseline workflow
|
||||
|
||||
Before production edits:
|
||||
|
||||
1. Run the full baseline build:
|
||||
|
||||
`ninja -j4 all_source progress semantic_progress`
|
||||
|
||||
2. Save a stable snapshot:
|
||||
|
||||
`python -m tools.campaign.stable_verdicts snapshot scratch/lane-a-before.json`
|
||||
|
||||
3. Save copies of:
|
||||
|
||||
- `build/semantic_report.json`
|
||||
- the progress report;
|
||||
- parked-function validation output;
|
||||
- object-admission audit output;
|
||||
- fake-match scan output;
|
||||
- per-unit `board.py` and `gate.py --all` results;
|
||||
- owner/data/COMMON/point inventories for all 11 units.
|
||||
|
||||
4. Validate parks:
|
||||
|
||||
`python -m tools.parked_functions`
|
||||
|
||||
5. Run object-admission audit:
|
||||
|
||||
`python tools/audit_object_admission.py`
|
||||
|
||||
6. Run tests:
|
||||
|
||||
`python -m pytest -q tools`
|
||||
|
||||
7. Run a fake-match baseline scan:
|
||||
|
||||
`python tools/fake_match_scan.py --format json source/ai`
|
||||
|
||||
8. Record the exact compiler flags for all 11 TUs from `build.ninja`.
|
||||
|
||||
9. For each unit, inventory:
|
||||
|
||||
- January function owners;
|
||||
- current candidate owners;
|
||||
- exact/residual/unwritten status;
|
||||
- meaningful and padded size;
|
||||
- normalized hashes;
|
||||
- relocation count and identities;
|
||||
- linkage/storage class;
|
||||
- parks and reopening criteria;
|
||||
- target and candidate data sections;
|
||||
- COMMON/BSS;
|
||||
- point-helper definitions;
|
||||
- target-absent candidate owners.
|
||||
|
||||
## 10. Function-level workflow
|
||||
|
||||
For each candidate:
|
||||
|
||||
1. Read current source and all prior reports first.
|
||||
2. Confirm it is not already exact or already accepted under another identity.
|
||||
3. Use `git log --all -- <file>` and `tools/campaign/branch_sweep.py` to census distinct historical source, but do not treat historical code as admitted.
|
||||
4. Inspect target and candidate using:
|
||||
|
||||
- `tools/campaign/gate.py`
|
||||
- `tools/campaign/alndiff.py`
|
||||
- `tools/campaign/tinfo.py`
|
||||
- `tools/campaign/relocdiff.py`
|
||||
- `tools/bijection_walk.py` where allocation bijection matters
|
||||
- `tools/campaign/namegap.py` only for identity proposals
|
||||
- Ghidra/DIA/raw PDB or MAP evidence as relevant.
|
||||
|
||||
5. Diagnose semantic structure before editing:
|
||||
|
||||
- missing or extra calls;
|
||||
- relocation multiplicity;
|
||||
- parameter width;
|
||||
- return type;
|
||||
- enum width/value;
|
||||
- aggregate identity/layout;
|
||||
- branch topology;
|
||||
- loop shape;
|
||||
- expression order;
|
||||
- source-owned repeated predicates or stores;
|
||||
- helper ownership and inlining;
|
||||
- local lifetime and scope;
|
||||
- declaration initialization;
|
||||
- frame extent;
|
||||
- x87 stack order;
|
||||
- calling convention and linkage.
|
||||
|
||||
6. Test bounded evidence-backed shapes with in-memory edits or scratch copies. Do not perform combinatorial permutation searches or random spelling sweeps.
|
||||
|
||||
7. Require a strict function gate for exact claims.
|
||||
|
||||
8. For changed units, compare the complete unit and preserve every inherited exact sibling.
|
||||
|
||||
9. Run the emitted-symbol point guard wherever January does not own the helper. For `ai_debug`, preserve its inherited genuine owner byte-for-byte and prevent any duplicate owner.
|
||||
|
||||
10. Run the fake-match scanner on every changed file and manually adjudicate every new lead.
|
||||
|
||||
11. Compare all codeowners, data, COMMON, runtime sections, relocations, linkage, COMDAT selection, and target-absent owners.
|
||||
|
||||
12. If still fuzzy, compare it against baseline. Retain it only if it is semantically more authentic and materially improves a documented structural defect. Similarity percentage alone is not enough.
|
||||
|
||||
13. For every rejected shape, save a concise negative result so later workers do not repeat it.
|
||||
|
||||
## 11. Config policy
|
||||
|
||||
No header changes are permitted.
|
||||
|
||||
Narrow configuration changes are allowed only as follows:
|
||||
|
||||
### `config/parked.json`
|
||||
|
||||
You may change entries only for functions in the 11 allowed TUs.
|
||||
|
||||
- Remove a park only when the function is independently verified strict exact.
|
||||
- Re-baseline an improved fuzzy function only when the retained source is house-rule compliant, genuinely better supported, and its new measurements and evidence are documented.
|
||||
- Do not change unrelated parks.
|
||||
- Do not use a park edit to hide a regression.
|
||||
- Keep fuzzy bytes at zero credit.
|
||||
|
||||
### `config/symbols.json`
|
||||
|
||||
You may edit only an entry belonging to an allowed TU and only when an original or independently authenticated name is established through January PDB/MAP, original source, or sufficiently strong private-symbol/call-graph evidence.
|
||||
|
||||
- A byte-equal alias or `namegap.py` proposal alone is insufficient.
|
||||
- Do not rename target symbols merely to make the comparator agree.
|
||||
- Land the name and corresponding source owner atomically.
|
||||
- Preserve old/new file offset, evidence source, and identity reasoning in the manifest.
|
||||
|
||||
### `config/config.json`
|
||||
|
||||
A per-TU `/QIfist` or whole-object status change is allowed only with direct target/compiler evidence and complete unit validation.
|
||||
|
||||
- No blanket compiler-option changes.
|
||||
- No unrelated object changes.
|
||||
- No “Matching” status until complete owner/data/extra-owner audit passes.
|
||||
- Do not add a semantic-match exception for a nonexact function.
|
||||
|
||||
No other configuration or policy file may change.
|
||||
|
||||
## 12. Wave cadence and commits
|
||||
|
||||
Work in coherent waves. Do not wait for exactly 10,000 bytes if a clean smaller wave is ready, but avoid one tiny commit per leaf unless isolation is necessary.
|
||||
|
||||
Suggested waves:
|
||||
|
||||
- Wave A1: small-unit closures.
|
||||
- Wave A2: actor looking and moving.
|
||||
- Wave A3: communication and perception.
|
||||
- Wave A4: AI debug and portfolio closeout.
|
||||
- Additional waves are allowed when evidence supports them.
|
||||
|
||||
For each wave:
|
||||
|
||||
1. Land minimal production/config patches.
|
||||
2. Independently review every changed function.
|
||||
3. Run all per-function and complete-TU gates.
|
||||
4. Run full Ninja once for the coherent batch.
|
||||
5. Take a stable after snapshot and diff against the frozen baseline, not merely the previous wave.
|
||||
6. Recompute semantic accepted bytes.
|
||||
7. Validate parks and admissions.
|
||||
8. Run changed-file fake scans and owner/data/COMMON/point checks.
|
||||
9. Run `git diff --check`.
|
||||
10. Commit code, config, and its evidence report together.
|
||||
|
||||
At each cumulative 10,000 newly verified meaningful-byte checkpoint, also run the full tools test suite and record the refreshed treemap/progress inputs. Do not claim the checkpoint until the semantic accepted ledger proves it.
|
||||
|
||||
Never squash away the evidence boundaries. Keep an ordered, cherry-pickable commit series.
|
||||
|
||||
## 13. Verification and accounting
|
||||
|
||||
Maintain these totals separately:
|
||||
|
||||
1. **New strict meaningful Halo bytes** — authoritative campaign credit from the accepted semantic ledger.
|
||||
2. **New strict padded bytes** — physical function-section gain from stable comparison.
|
||||
3. **New strict functions**.
|
||||
4. **Fuzzy meaningful bytes changed or improved** — always zero exact credit.
|
||||
5. **Whole-object completions** — separate status, never duplicate function credit.
|
||||
6. **Regressions** — must remain zero.
|
||||
|
||||
Do not report:
|
||||
|
||||
- diagnostic similarity as byte credit;
|
||||
- target-size totals for nonexact bodies as “progress”;
|
||||
- already exact functions as new;
|
||||
- config-only identity changes without admission proof;
|
||||
- external/vendor bytes;
|
||||
- duplicate aliases or embedded labels;
|
||||
- gross gains that conceal losses.
|
||||
|
||||
Every exact row in the final manifest must include:
|
||||
|
||||
- unit;
|
||||
- function;
|
||||
- meaningful bytes;
|
||||
- padded bytes;
|
||||
- target section/index;
|
||||
- target and candidate normalized SHA-256;
|
||||
- relocation count and identity result;
|
||||
- before/after verdict;
|
||||
- evidence basis;
|
||||
- reviewer;
|
||||
- source commit;
|
||||
- owner/data/COMMON/point result.
|
||||
|
||||
Every fuzzy row must include:
|
||||
|
||||
- zero credit explicitly;
|
||||
- baseline and final measurements;
|
||||
- what source defect was corrected;
|
||||
- why the retained code is more authentic;
|
||||
- remaining differing regions;
|
||||
- rejected alternatives;
|
||||
- precise reopening evidence.
|
||||
|
||||
## 14. Final verification
|
||||
|
||||
On final tip:
|
||||
|
||||
1. Confirm `git status --short` is empty.
|
||||
2. Run:
|
||||
|
||||
`ninja -j4 all_source progress semantic_progress`
|
||||
|
||||
3. Save:
|
||||
|
||||
`python -m tools.campaign.stable_verdicts snapshot scratch/lane-a-after.json`
|
||||
|
||||
4. Diff against the frozen baseline snapshot:
|
||||
|
||||
`python -m tools.campaign.stable_verdicts diff scratch/lane-a-before.json scratch/lane-a-after.json`
|
||||
|
||||
5. Run:
|
||||
|
||||
- `python -m tools.parked_functions`
|
||||
- `python tools/audit_object_admission.py`
|
||||
- `python tools/fake_match_scan.py --format json source/ai`
|
||||
- `python -m pytest -q tools`
|
||||
- `git diff --check 6130661c9585fdb2785b3ff6bdb2ad0cfef0520c..HEAD`
|
||||
|
||||
6. Verify all inherited exact functions remain exact.
|
||||
7. Verify no production C/H file outside the 11-file allowlist changed.
|
||||
8. Verify no Xbox/vendor source changed.
|
||||
9. Verify no target object, build tool, compiler, comparator, or acceptance policy changed.
|
||||
10. Verify all data, COMMON/BSS, owner, linkage, COMDAT, and point-helper inventories.
|
||||
11. Verify every retained fake-scan lead is inherited or individually evidence-approved.
|
||||
12. Recompute exact meaningful and padded gains from final production, not worker self-reports.
|
||||
13. List the ordered commit range from baseline to tip.
|
||||
14. Do not push and do not touch canonical.
|
||||
|
||||
## 15. Required deliverables
|
||||
|
||||
Create:
|
||||
|
||||
- `docs/object_matching_logs/claude_lane_a_ai_core_HANDOFF_20260920.md`
|
||||
- `docs/object_matching_logs/claude_lane_a_ai_core_admission_manifest_20260920.json`
|
||||
- `docs/object_matching_logs/claude_lane_a_ai_core_rejected_hypotheses_20260920.md`
|
||||
|
||||
The handoff must contain:
|
||||
|
||||
- worktree, branch, baseline, and final tip;
|
||||
- exact ordered commits;
|
||||
- complete changed-file list;
|
||||
- baseline and final accepted totals;
|
||||
- strict meaningful, padded, and function gains;
|
||||
- fuzzy extent at zero credit;
|
||||
- zero-regression proof;
|
||||
- per-wave results;
|
||||
- per-function evidence;
|
||||
- config changes and why;
|
||||
- all header prerequisites deferred;
|
||||
- every remaining owner and reopening condition;
|
||||
- verification commands and actual outputs;
|
||||
- whether the tree is clean;
|
||||
- explicit statement: nothing pushed and canonical untouched.
|
||||
|
||||
The JSON manifest must be machine-readable and include hashes, measurements, relocations, evidence, reviewer decisions, exact/fuzzy disposition, and credit for every retained change.
|
||||
|
||||
Preserve compact reproducible scratch evidence locally, but do not commit huge generated disassemblies, copied binaries, object files, or private symbol assets. Record their paths and hashes in the handoff.
|
||||
|
||||
## 16. Completion standard
|
||||
|
||||
Do not stop because one large function reaches an allocator tie. Move to the next function and continue the portfolio.
|
||||
|
||||
Do not declare the lane “exhausted” unless:
|
||||
|
||||
- every residual/unwritten owner in all 11 units was inventoried;
|
||||
- previous work was checked for duplication;
|
||||
- all existing high-confidence Astra mechanisms were either integrated, rejected with current evidence, or superseded;
|
||||
- every new evidence-backed structural hypothesis was tested in bounded form;
|
||||
- every retained change follows the house rules;
|
||||
- every exact claim passed strict production verification;
|
||||
- every nonexact improvement is explicitly zero credit;
|
||||
- every untouched blocker has a concrete reopening condition rather than a generic “compiler tie” label.
|
||||
|
||||
The desired outcome is the largest defensible strict gain possible from these 79,657 remaining Halo-owned bytes, plus a materially better research boundary for everything not yet exact. Source authenticity, semantics, ownership, and zero regressions take precedence over a large but artificial headline number.
|
||||
@@ -1,444 +0,0 @@
|
||||
HALO JANUARY EXACT-MATCH CAMPAIGN — CLAUDE LANE B
|
||||
AI ACTIONS, PATHFINDING, GAMEPLAY, PHYSICS/COLLISION, BIPEDS/UNITS/VEHICLES
|
||||
|
||||
MISSION
|
||||
|
||||
Work only from canonical commit:
|
||||
|
||||
6130661c9585fdb2785b3ff6bdb2ad0cfef0520c
|
||||
branch: jonas/exact-pilots
|
||||
|
||||
Your lane contains exactly 75,377 currently non-exact meaningful Halo-owned code bytes. Reconstruct as much of this entire allocation as possible, aiming for at least +50,000 newly proven strict meaningful bytes and ultimately all 75,377. Do not manufacture matches to meet the number. If evidence is insufficient, do more research; do not declare human-written Halo code inherently unmatchable.
|
||||
|
||||
This is one of four concurrent, disjoint Claude lanes. Stay inside the source-unit allowlist below. Do not touch Xbox/XDK libraries, Bink/vendor code, libcmt, or any source unit assigned to another lane.
|
||||
|
||||
Administrative “reserved,” “do not spend,” and old lane-scope holds are lifted inside this allowlist. Scientific rejections are not automatically erased: do not repeat an exhausted spelling unless new evidence refutes its premise. Parked functions in this lane may be reopened when new evidence satisfies or invalidates their recorded criteria.
|
||||
|
||||
Do not push. Do not modify the canonical checkout or canonical branch. Work in a new local worktree and branch created directly from 6130661c.
|
||||
|
||||
REQUIRED WORKTREE
|
||||
|
||||
Create a clean worktree such as:
|
||||
|
||||
C:\halo-worktrees\claude-lane-b-ai-physics-units-20260920
|
||||
branch: claude/lane-b-ai-physics-units-20260920
|
||||
|
||||
If either name already exists, use a unique suffixed name. Never reset, delete, clean, or repurpose an existing worktree.
|
||||
|
||||
Before editing, prove:
|
||||
|
||||
- `git rev-parse HEAD` is exactly `6130661c9585fdb2785b3ff6bdb2ad0cfef0520c`.
|
||||
- `git status --short` is empty.
|
||||
- The configured full build passes.
|
||||
- A complete stable-verdict snapshot has been saved.
|
||||
- Baseline meaningful, padded, function, object, park, and test totals have been recorded.
|
||||
|
||||
ALLOWED SOURCE UNITS — NO OTHERS
|
||||
|
||||
The values are the current meaningful residual-byte ceilings at the frozen baseline.
|
||||
|
||||
AI/action/path family — 20,507 bytes:
|
||||
|
||||
- `source/ai/action_charge.c` — 3,246
|
||||
- `source/ai/action_converse.c` — 248
|
||||
- `source/ai/action_obey.c` — 984
|
||||
- `source/ai/action_vehicle.c` — 1,679
|
||||
- `source/ai/actions.c` — 1,981
|
||||
- `source/ai/actor_combat.c` — 1,529
|
||||
- `source/ai/actor_type_flood.c` — 1,295
|
||||
- `source/ai/actor_type_infection.c` — 3,609
|
||||
- `source/ai/path.c` — 2,783
|
||||
- `source/ai/path_obstacle_avoidance.c` — 1,569
|
||||
- `source/ai/path_obstacles.c` — 160
|
||||
- `source/ai/path_smoothing.c` — 326
|
||||
- `source/ai/path_structure_bsp.c` — 1,098
|
||||
|
||||
Game family — 5,186 bytes:
|
||||
|
||||
- `source/game/aim_assist.c` — 1,173
|
||||
- `source/game/game.c` — 92
|
||||
- `source/game/game_engine_king.c` — 444
|
||||
- `source/game/game_engine_race.c` — 215
|
||||
- `source/game/player_control.c` — 1,577
|
||||
- `source/game/players.c` — 1,685
|
||||
|
||||
Memory family — 821 bytes:
|
||||
|
||||
- `source/memory/stack_memory_pool.c` — 821
|
||||
|
||||
Physics/collision family — 25,691 bytes:
|
||||
|
||||
- `source/physics/breakable_surfaces.c` — 4,020
|
||||
- `source/physics/collision_bsp.c` — 3,158
|
||||
- `source/physics/collision_debug.c` — 4,182
|
||||
- `source/physics/collisions.c` — 4,744
|
||||
- `source/physics/physics.c` — 9,587
|
||||
|
||||
Scenario family — 380 bytes:
|
||||
|
||||
- `source/scenario/wind.c` — 380
|
||||
|
||||
Units family — 22,792 bytes:
|
||||
|
||||
- `source/units/biped_limp_noodle.c` — 3,443
|
||||
- `source/units/bipeds.c` — 13,147
|
||||
- `source/units/unit_dialogue.c` — 1,041
|
||||
- `source/units/units.c` — 48
|
||||
- `source/units/vehicles.c` — 5,113
|
||||
|
||||
The corresponding genuine owner headers may be changed only when required for one of these units and only under the header protocol below. Do not edit generic shared headers such as `cseries.h`, `real_math.h`, object/tag core headers, bitmap headers, weapon headers, or unrelated subsystem headers. If a correct reconstruction requires an out-of-lane shared-header change, preserve the source candidate in scratch, document the exact required header packet and blast radius, and continue elsewhere.
|
||||
|
||||
The only permitted non-source edits are:
|
||||
|
||||
- lane-specific entries in `config/parked.json`;
|
||||
- independently authenticated lane-specific names in `config/symbols.json`;
|
||||
- lane documentation under `docs/object_matching_logs/`.
|
||||
|
||||
Do not edit build flags, tools, `semantic_matches.json`, semantic overrides, object-admission overrides, or unrelated configuration to make a candidate appear accepted.
|
||||
|
||||
READ THESE BEFORE EDITING
|
||||
|
||||
Read these files completely:
|
||||
|
||||
- `docs/campaign_house_rules.md`
|
||||
- `docs/campaign_throughput_lessons.md`
|
||||
- `docs/common_constants.md`
|
||||
- `docs/assertions.md`
|
||||
- `docs/matching_methodology.md`
|
||||
- `docs/exact_match_acceleration_playbook.md`
|
||||
- `docs/object_matching_logs/opus5_next150_compiler_laws_20260916.md`
|
||||
- `docs/object_matching_logs/opus5_next150_compiler_laws_round2_20260916.md`
|
||||
- `docs/object_matching_logs/astra_90pct_canonical_reconciliation_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_HANDOFF_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_research_atlas_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_rejected_hypotheses_20260920.md`
|
||||
- `docs/object_matching_logs/astra_90pct_admission_manifest_20260920.json`
|
||||
|
||||
Then read the relevant Astra evidence before touching its corresponding family:
|
||||
|
||||
- action charge:
|
||||
- `astra_90pct_wave13_action_charge_setup_20260920.md`
|
||||
- `astra_90pct_wave13_action_charge_primary_independent_20260920.md`
|
||||
- `astra_90pct_wave13_action_charge_independent_20260920.md`
|
||||
- `astra_90pct_wave13_call_sequence_census_20260920.md`
|
||||
- `astra_90pct_research8_action_charge_20260920.md`
|
||||
- `astra_90pct_research8_action_charge_independent_20260920.md`
|
||||
- aim assist:
|
||||
- `astra_90pct_research8_aim_assist_20260920.md`
|
||||
- `astra_90pct_research8_aim_assist_independent_20260920.md`
|
||||
- infection:
|
||||
- `astra_90pct_research7_infection_20260920.md`
|
||||
- collisions:
|
||||
- `astra_90pct_wave2_collisions_20260920.md`
|
||||
- physics:
|
||||
- `astra_90pct_wave4_physics_20260920.md`
|
||||
- `astra_90pct_wave4_physics_independent_review_20260920.md`
|
||||
- `astra_90pct_wave4_frame_statistics_20260920.md`
|
||||
- collision debug:
|
||||
- `astra_90pct_wave6_collision_debug_20260920.md`
|
||||
- bipeds:
|
||||
- `astra_90pct_wave3_bipeds_packet_20260920.md`
|
||||
- `astra_90pct_wave3_bipeds_independent_review_20260920.md`
|
||||
- `astra_90pct_research18_bipeds_probe_20260920.md`
|
||||
- `astra_90pct_research18_biped_private_owner_20260920.md`
|
||||
- `astra_90pct_research11_biped_moving_20260920.md`
|
||||
- vehicles:
|
||||
- `astra_90pct_research7_vehicles_20260920.md`
|
||||
- `astra_90pct_vehicle_independent_review_20260920.md`
|
||||
- path/obstacles:
|
||||
- `astra_90pct_wave17_obstacle_owner_20260920.md`
|
||||
- players:
|
||||
- `astra_90pct_wave17_player_probe_20260920.md`
|
||||
- `astra_90pct_wave17_player_private_owner_20260920.md`
|
||||
- `astra_90pct_wave17_player_independent_20260920.md`
|
||||
- `astra_90pct_research16_player_context_20260920.md`
|
||||
|
||||
The complete immutable Astra evidence package is here:
|
||||
|
||||
`C:\Users\isabe\Documents\Codex\2026-09-20\files-pasted-by-the-user-halo\outputs`
|
||||
|
||||
Its `SHA256SUMS.json` and package README define its integrity and contents. The large function atlas is research evidence, not current accounting authority. The current build at 6130661c is authoritative.
|
||||
|
||||
IMPORTANT ASTRA BOUNDARY
|
||||
|
||||
Astra already made `_action_charge_setup` and `_player_examine_nearby_unit` strict exact. They and every other exact baseline function are immutable. Do not “improve,” restyle, or rewrite an exact function.
|
||||
|
||||
Use Astra’s rejected-hypothesis ledger to avoid rerunning identical failed spellings. A negative result is not a permanent ban when you have genuinely new evidence, but state what new evidence invalidates the old premise before spending on it. “Try it again” is not new evidence.
|
||||
|
||||
EVIDENCE SOURCES
|
||||
|
||||
January is the byte authority:
|
||||
|
||||
`C:\Users\isabe\Downloads\Halo Combat Evolved (Jan 14, 2002 prototype)`
|
||||
|
||||
This directory contains the January `cachebeta` XBE variants, `cachebeta.exe`, and `cachebeta.pdb`. The PDB has useful public symbols but lacks Halo local-variable and line records. Do not claim those missing records exist.
|
||||
|
||||
Additional evidence, never interchangeable byte targets:
|
||||
|
||||
- October 2001 prototype:
|
||||
`C:\Users\isabe\Downloads\Halo - Combat Evolved (Oct 12, 2001 prototype)\Halo 2276`
|
||||
- supplied later symbol executables and three original Bungie source files:
|
||||
`C:\Users\isabe\Downloads\haloleak2024\halo1`
|
||||
- open-source Marathon reference:
|
||||
`C:\Users\isabe\Documents\Codex\2026-07-13\i-w\_research-marathon-source-agent-20260904`
|
||||
- locally mirrored public Halo research:
|
||||
- `C:\Users\isabe\Documents\Codex\2026-07-13\i-w\_research-punpck-halo`
|
||||
- `C:\Users\isabe\Documents\Codex\2026-07-13\i-w\_research-stian-halo`
|
||||
- the other `_research-*` trees beside them.
|
||||
|
||||
The supplied 2020 executables have confirmed source differences. They may establish names, types, broad control-flow topology, ownership, and semantic intent, but their instructions are not January byte proof.
|
||||
|
||||
Use Ghidra and DIA where useful. Use the installed IDA Free interactively for ambiguous high-value functions when available, but it has no working callable scripting/RPC interface; do not waste the campaign repeatedly probing for one or declare the lane blocked because IDA cannot be automated. Analyze supplied binaries as data only—never execute them.
|
||||
|
||||
HOUSE RULES — ALL ARE BINDING
|
||||
|
||||
1. Format a no-argument function with `void` on its own line inside the parameter list.
|
||||
2. Put every parameter on its own line.
|
||||
3. End every function with an explicit return: `return;` for `void`, an appropriate value for non-void functions.
|
||||
4. Use subsystem typed macros wrapping `tag_get`; do not scatter raw typed casts.
|
||||
5. Use typed object-access macros instead of repeated casts after raw `object_get`.
|
||||
6. Preserve January’s inline schedule and do not emit a `point_from_line3d` COMDAT.
|
||||
7. Give private functions authentic or descriptive project-style names; never use `code_XXXXXXXX` or address names.
|
||||
8. Give globals authentic or descriptive project-style names; never use `bss_XXXXXXXX` or address names.
|
||||
9. Put prototypes in their genuine owner locations, not unrelated consumer `.c` files.
|
||||
10. Inline assembly is exceptional. It may be used sparingly in a genuine helper/math routine only when target evidence proves ordinary VC7 C cannot emit the required instructions. Earlier asm rulings are function-specific and do not create blanket permission.
|
||||
11. If easy exactness fails, preserve credible, useful fuzzy source, document it, and park it at zero credit.
|
||||
12. Prioritize small objects and small unwritten functions within these substantially reconstructed families.
|
||||
13. Avoid manual or forced inlining. Reproduce the natural helper boundary and January schedule.
|
||||
14. Use Marathon as a style/semantic reference, not as January byte proof.
|
||||
15. If a `.c` file has no dedicated header, use the closest genuine associated header.
|
||||
16. Use correct enum constants in switch tables; do not replace missing research with raw magic case numbers.
|
||||
17. Combine declaration and initialization when practical and source-authentic.
|
||||
18. Prefer appropriate `cseries.h` macros over manual bitwise logic.
|
||||
19. Use project-defined types such as `real`, not generic substitutes such as `float`.
|
||||
20. Reject fake matching and source Bungie almost certainly would not have written.
|
||||
21. Reject nonsensical logic even when it coincidentally byte-matches.
|
||||
22. Use `/QIfist` only where target/compiler evidence requires it. It is a per-TU property, not a blanket flag. Audit the complete TU and callers before changing it.
|
||||
23. Assertions/warnings/halts must follow `docs/assertions.md`. Predicates state required invariants, diagnostics remain lazy, and the weapon-connected example requires `!TEST_FLAG(...)`. Do not hand-expand `display_assert` when the genuine `assert`/`dassert`/`vassert` family is appropriate.
|
||||
24. Never invent undefined behavior, uninitialized reads, out-of-bounds access, representation punning, volatile steering, dummy locals, redundant assignments, self-assignments, impossible conditions, raw-byte emission, pragmas, compiler barriers, fake globals, or arbitrary struct offsets to force bytes.
|
||||
25. If January conclusively proves an original bug that cannot be expressed in defined natural C, preserve the evidence and candidate at zero credit and request a narrow owner ruling. Do not silently land UB.
|
||||
26. Correct semantics, ABI, linkage, symbol ownership, data ownership, and source authenticity are required in addition to byte equality.
|
||||
|
||||
STRICT CREDIT
|
||||
|
||||
A function receives exact credit only when the current strict comparator proves the January and candidate sections identical, including size, normalized bytes, relocation layout and identities, and the required section/owner metadata.
|
||||
|
||||
Do not count:
|
||||
|
||||
- fuzzy or parked functions;
|
||||
- “100%” fuzzy similarity;
|
||||
- same-size functions;
|
||||
- matching relocation counts without matching instructions;
|
||||
- semantic overrides;
|
||||
- asm-implemented or externally supplied rows;
|
||||
- padded alignment bytes as meaningful bytes;
|
||||
- pre-existing exact functions;
|
||||
- worker estimates;
|
||||
- renamed functions without independent name provenance;
|
||||
- whole objects whose data/BSS/linkage/extra-owner state has not been audited.
|
||||
|
||||
Keep these totals separate in every report:
|
||||
|
||||
1. newly strict exact functions;
|
||||
2. newly strict meaningful code bytes from the accepted ledger;
|
||||
3. newly strict padded bytes from stable-verdict diff;
|
||||
4. credible fuzzy bytes retained at zero credit;
|
||||
5. object-level completions after complete code/data/ownership audit.
|
||||
|
||||
Do not mark an object green/Matching merely because all visible functions look exact.
|
||||
|
||||
ANTI-DUPLICATION AND CURRENT-STATE INVENTORY
|
||||
|
||||
Before source work:
|
||||
|
||||
1. Run the current board on every allowed unit.
|
||||
2. Record each target function’s target-section identity, baseline status, meaningful/padded size, relocation count, frame size, and current owner.
|
||||
3. Query the Astra function atlas, handoff, and rejection ledger by function.
|
||||
4. Run `tools/campaign/branch_sweep.py` for each allowed source file to locate better historical bodies without blindly cherry-picking them.
|
||||
5. Map promising blobs back to commits and read their ledgers/reviews.
|
||||
6. Treat historical code only as a donor hypothesis. Recompile against 6130661c and re-audit it under current house rules.
|
||||
7. Never assign two workers the same `.c` file.
|
||||
8. Never count a function already exact at baseline as a lane gain.
|
||||
|
||||
Use the current source/config trees, not an old patch, old all-lanes treemap union, or a prior worker’s headline total.
|
||||
|
||||
THROUGHPUT STRATEGY
|
||||
|
||||
Do not spend the campaign fighting one register-allocation tie while unwritten or structurally wrong functions remain.
|
||||
|
||||
Start with a closeout wave over the smallest residual objects:
|
||||
|
||||
- `units` — 48
|
||||
- `game` — 92
|
||||
- `path_obstacles` — 160
|
||||
- `game_engine_race` — 215
|
||||
- `action_converse` — 248
|
||||
- `path_smoothing` — 326
|
||||
- `wind` — 380
|
||||
- `game_engine_king` — 444
|
||||
- `stack_memory_pool` — 821
|
||||
- `action_obey` — 984
|
||||
|
||||
Within every unit, prioritize:
|
||||
|
||||
1. unwritten bodies;
|
||||
2. proven missing calls/helper boundaries/incorrect signatures or types;
|
||||
3. structural control-flow and frame-layout defects;
|
||||
4. exact historical donors that pass current authenticity review;
|
||||
5. only then near-tie scheduling/x87/register residuals.
|
||||
|
||||
After a few bounded source-shape attempts without new evidence, move to another function. Do not create a bespoke Python tester for every 200–500 byte function. Use the universal gate, relocation diff, aligned disassembly, and stable sweep. Add a runtime harness only when behavior or ABI is genuinely ambiguous.
|
||||
|
||||
Return to hard functions after a research pass across:
|
||||
|
||||
- public/private symbol provenance;
|
||||
- caller and callee graphs;
|
||||
- strings/assert paths/line-number evidence;
|
||||
- target relocation identities;
|
||||
- cross-build topology;
|
||||
- analogous exact functions in January;
|
||||
- C2 compiler probes;
|
||||
- Ghidra/IDA/DIA evidence;
|
||||
- original Bungie/Marathon coding idioms.
|
||||
|
||||
A historical park is a research index, not an excuse to stop. Test its explicit reopen criterion. If the criterion is stale or contradicted, reopen it honestly and update only that lane-specific park entry.
|
||||
|
||||
PARALLEL AGENT ARCHITECTURE
|
||||
|
||||
Use an orchestrator plus workers and independent adversarial reviewers.
|
||||
|
||||
- One worker per `.c` file; files must remain strictly disjoint.
|
||||
- Workers use `tools/campaign/gate.py` and scratch objects only.
|
||||
- Workers do not run `ninja`, `configure.py`, full pytest, or shared-build commands.
|
||||
- Workers do not edit headers, config, tools, or commit.
|
||||
- Workers report exact baseline counts and only newly gained functions.
|
||||
- The orchestrator reviews and applies candidates to the real source.
|
||||
- A different agent independently reviews every proposed landing for semantics, house rules, ownership, and exactness.
|
||||
- The orchestrator alone performs full builds, config updates, and commits.
|
||||
|
||||
`gate.py` is safe for concurrent TU work because it writes PID-isolated scratch objects. Useful forms include:
|
||||
|
||||
- `python tools/campaign/gate.py <unit>`
|
||||
- `python tools/campaign/gate.py <unit> --fn <function>`
|
||||
- `python tools/campaign/gate.py <unit> --source <scratch-source>`
|
||||
- `python tools/campaign/gate.py <unit> --edits <json>`
|
||||
- `python tools/campaign/gate.py <unit> --out <scratch-object>`
|
||||
- `python tools/campaign/gate.py <unit> --forbid-emitted-symbol _point_from_line3d --all`
|
||||
|
||||
Do not rely on `gate.py --disas` after instruction counts diverge; it is index-zipped. Use:
|
||||
|
||||
- `python tools/campaign/alndiff.py <unit> <function>`
|
||||
- `python tools/campaign/relocdiff.py <unit> <function>`
|
||||
- `python tools/campaign/tinfo.py <unit> --fn <function>`
|
||||
- `python tools/bijection_walk.py --unit <unit> <function> -v`
|
||||
|
||||
Use spelling sweeps only to test evidence-backed hypotheses. A successful brute-force spelling is not authenticity evidence by itself.
|
||||
|
||||
HEADER PROTOCOL
|
||||
|
||||
Header edits are high risk because VC7 allocation can change in unrelated includers based only on declaration position.
|
||||
|
||||
Before touching a header:
|
||||
|
||||
1. Enumerate every including `.c` with `rg`.
|
||||
2. Prove the declaration belongs in that header.
|
||||
3. Confirm it cannot correctly remain TU-private in the owner `.c`.
|
||||
4. Save a pristine baseline snapshot.
|
||||
5. Make the header change as a separate prerequisite commit.
|
||||
6. Rebuild and compare every dependent TU against pristine.
|
||||
7. Run the whole-tree stable sweep.
|
||||
8. Reject the header change if it loses any inherited exact function, even if the lane’s net total rises.
|
||||
9. Never compensate for a header regression with unrelated source steering.
|
||||
|
||||
Private structs, enums, helpers, and prototypes should remain in their genuine owner TU when historically and semantically appropriate. Public prototypes belong in the real subsystem header, never copied into whichever `.c` happens to call them.
|
||||
|
||||
CONFIG AND NAMING POLICY
|
||||
|
||||
`config/parked.json` may change only for functions in this allowlist:
|
||||
|
||||
- remove an entry after current strict proof;
|
||||
- remeasure it when an admitted source/header change legitimately changes the residual;
|
||||
- add a credible fuzzy landing with measured remaining differences and a concrete reopen criterion.
|
||||
|
||||
`config/symbols.json` may change only when the name has independent evidence from a January public, PDB, source/map artifact, unambiguous cross-build identity plus caller graph, or similarly strong provenance. A unique byte alias is a proposal, not name proof.
|
||||
|
||||
Do not retain `code + address` or `bss + address` identifiers in finished source. If the original private name is unrecoverable, use a descriptive project-convention name, label it as descriptive rather than proven, and document the evidence.
|
||||
|
||||
FULL VERIFICATION
|
||||
|
||||
At baseline:
|
||||
|
||||
- full configured `ninja -j4 all_source progress semantic_progress`;
|
||||
- `python -m tools.campaign.stable_verdicts snapshot scratch/lane_b_before.json`;
|
||||
- `python -m tools.campaign.board`;
|
||||
- park validation;
|
||||
- object-admission audit;
|
||||
- test suite;
|
||||
- changed-scope fake-scan baseline.
|
||||
|
||||
After each coherent wave—and at least every +10,000 newly proven meaningful bytes—the orchestrator must:
|
||||
|
||||
1. run all affected per-function strict gates;
|
||||
2. run the `_point_from_line3d` emitted-symbol guard on every changed TU;
|
||||
3. run a full `ninja -j4 all_source progress semantic_progress`;
|
||||
4. capture a new stable-verdict snapshot;
|
||||
5. diff it against the frozen lane baseline and prove zero exact regressions;
|
||||
6. inspect accepted meaningful totals from the semantic report;
|
||||
7. validate parks with zero stale/invalid entries;
|
||||
8. run the object-admission audit;
|
||||
9. run `tools/fake_match_scan.py` over every changed source file and adjudicate every new finding;
|
||||
10. audit emitted code/data/COMMON owners;
|
||||
11. run relevant runtime/ABI tests and the full pytest suite at final;
|
||||
12. run `git diff --check`;
|
||||
13. review the complete diff against the source allowlist.
|
||||
|
||||
No inherited exact regression is permitted. Net gain does not excuse one lost exact function.
|
||||
|
||||
COMMITS
|
||||
|
||||
Commit in coherent, reviewable waves, preferably family/file packets. Keep prerequisite header changes separate. Keep zero-credit fuzzy preservation separate from strict admissions. Do not create a giant opaque final commit.
|
||||
|
||||
Every commit message and wave record must identify:
|
||||
|
||||
- affected units/functions;
|
||||
- new strict meaningful and padded bytes;
|
||||
- fuzzy bytes, separately;
|
||||
- stable regression result;
|
||||
- config/header changes;
|
||||
- evidence used;
|
||||
- independent reviewer result.
|
||||
|
||||
Do not push. Do not merge into `jonas/exact-pilots`. Leave a clean local lane.
|
||||
|
||||
FINAL DELIVERABLES
|
||||
|
||||
Create:
|
||||
|
||||
- `docs/object_matching_logs/claude_lane_b_HANDOFF_20260920.md`
|
||||
- `docs/object_matching_logs/claude_lane_b_admission_manifest_20260920.json`
|
||||
- `docs/object_matching_logs/claude_lane_b_rejected_hypotheses_20260920.md`
|
||||
|
||||
The handoff must include:
|
||||
|
||||
- worktree, branch, frozen base, and final tip;
|
||||
- ordered commit list;
|
||||
- exact changed-file list;
|
||||
- baseline and final accepted ledgers;
|
||||
- newly strict functions with unit, target section, meaningful bytes, padded bytes, relocation counts, and commit;
|
||||
- fuzzy functions retained at zero credit with fresh measurements;
|
||||
- all header/config edits and their blast-radius proofs;
|
||||
- exact-regression proof;
|
||||
- test/build/park/admission/fake-scan results;
|
||||
- remaining function-by-function inventory;
|
||||
- concrete next evidence required for every remaining substantial function;
|
||||
- any candidates held for a narrow owner ruling;
|
||||
- confirmation that no out-of-lane source, vendor library, canonical checkout, or remote branch was touched.
|
||||
|
||||
The JSON manifest must be machine-readable and include baseline/final hashes, per-function evidence, source provenance, strict verdict, semantic-credit status, reviewer decision, and commit hash.
|
||||
|
||||
If context or token budget becomes low, stop launching new probes. Finish the current coherent packet, run the complete verification, commit it, write the handoff/manifest, and leave the tree clean. Do not leave valuable work uncommitted or source claims unsupported.
|
||||
|
||||
Do not stop merely because the headline +50,000 target looks difficult. Continue broad, evidence-driven work across the full 75,377-byte allocation. The valid stopping conditions are:
|
||||
|
||||
- every allocated byte is strict exact; or
|
||||
- every remaining row has received a fresh evidence pass, all admissible improvements are committed, and each unresolved function has a specific documented blocker/reopen criterion rather than a generic “compiler tie” claim.
|
||||
@@ -1,564 +0,0 @@
|
||||
You are Claude Opus 5 running Lane C of the Halo: Combat Evolved January 14, 2002 exact-match campaign.
|
||||
|
||||
Your task is to reconstruct and strictly verify the remaining Halo-owned graphics/UI code assigned below. Work for maximum durable progress, not a brief sampling pass.
|
||||
|
||||
## 1. Frozen baseline and isolation
|
||||
|
||||
The immutable starting point is:
|
||||
|
||||
- Branch: `jonas/exact-pilots`
|
||||
- Commit: `6130661c9585fdb2785b3ff6bdb2ad0cfef0520c`
|
||||
- Canonical checkout, READ ONLY:
|
||||
`C:\Users\isabe\Documents\Codex\2026-07-13\i-w\worktrees\astra-reconcile-20260920`
|
||||
|
||||
Use a dedicated worktree and branch, for example:
|
||||
|
||||
- Worktree: `C:\halo-worktrees\claude-lane-c-graphics-ui-20260920`
|
||||
- Branch: `claude/lane-c-graphics-ui-20260920`
|
||||
|
||||
If that worktree or branch already exists, inspect it instead of blindly recreating it. Before doing any work, prove:
|
||||
|
||||
```text
|
||||
git status --short
|
||||
git rev-parse HEAD
|
||||
```
|
||||
|
||||
The tree must be clean and HEAD must be exactly `6130661c9585fdb2785b3ff6bdb2ad0cfef0520c`.
|
||||
|
||||
Never edit the canonical checkout, never move or reset `jonas/exact-pilots`, and never push. Make local commits only in your dedicated lane. Do not cherry-pick another lane wholesale.
|
||||
|
||||
## 2. Objective
|
||||
|
||||
This lane begins with approximately **83,898 meaningful non-exact Halo code bytes** in its assigned units.
|
||||
|
||||
Campaign target:
|
||||
|
||||
- Primary target: at least **50,000 newly proven strict meaningful exact bytes**.
|
||||
- Stretch target: close the entire **83,898-byte** assigned residual pool.
|
||||
- Also maximize genuinely complete, whole-object `Matching` closures.
|
||||
- Preserve credible, house-rule-compliant fuzzy improvements at zero matching credit when exactness is not yet attainable.
|
||||
|
||||
Do not stop after one or two low-yield waves. Do not declare the target impossible merely by summing current park entries. Parks are prior evidence and hypotheses, not eternal prohibitions; reopen them only when their recorded criteria or genuinely new evidence justify it.
|
||||
|
||||
A lower result is acceptable only after every in-scope residual has received a current-baseline classification and all high-confidence structural opportunities have been pursued. “Register allocation tie” or “compiler noise” requires evidence from the existing classifiers or controlled experiments, not intuition.
|
||||
|
||||
Count only gains relative to commit `6130661c`. Pre-existing exact functions, donor-relative gains, fuzzy bodies, helper COMDATs, and already-integrated Astra work are not new credit.
|
||||
|
||||
## 3. Exclusive source scope
|
||||
|
||||
Only the following Halo translation units are assigned to this lane. The byte figures are starting estimates and must be remeasured at the frozen baseline.
|
||||
|
||||
### Bitmaps — 8,790 bytes
|
||||
|
||||
```text
|
||||
source/bitmaps/bitmap_group.c 995
|
||||
source/bitmaps/bitmap_utilities.c 2,362
|
||||
source/bitmaps/bitmaps.c 1,287
|
||||
source/bitmaps/s3tc/s3tc.c 4,146
|
||||
```
|
||||
|
||||
### Interface/UI — 32,470 bytes
|
||||
|
||||
```text
|
||||
source/interface/first_person_weapons.c 1,533
|
||||
source/interface/hud.c 1,744
|
||||
source/interface/hud_draw.c 364
|
||||
source/interface/hud_messaging.c 2,922
|
||||
source/interface/hud_nav_points.c 1,618
|
||||
source/interface/hud_weapon.c 7,696
|
||||
source/interface/interface.c 2,981
|
||||
source/interface/motion_sensor.c 3,144
|
||||
source/interface/progress_bar.c 349
|
||||
source/interface/ui_widget.c 6,425
|
||||
source/interface/ui_widget_game_data_input_functions.c 1,008
|
||||
source/interface/virtual_keyboard.c 2,686
|
||||
```
|
||||
|
||||
### Rasterizer — 34,352 bytes
|
||||
|
||||
```text
|
||||
source/rasterizer/rasterizer_frame_statistics.c 4,236
|
||||
source/rasterizer/rasterizer_geometry.c 1,179
|
||||
source/rasterizer/rasterizer_lights.c 3,049
|
||||
source/rasterizer/xbox/rasterizer_xbox_active_camouflage.c 2,014
|
||||
source/rasterizer/xbox/rasterizer_xbox_environment.c 4,957
|
||||
source/rasterizer/xbox/rasterizer_xbox_environment_fog.c 4,685
|
||||
source/rasterizer/xbox/rasterizer_xbox_hardware_bitmaps.c 388
|
||||
source/rasterizer/xbox/rasterizer_xbox_hardware_geometry.c 337
|
||||
source/rasterizer/xbox/rasterizer_xbox_lights.c 2,338
|
||||
source/rasterizer/xbox/rasterizer_xbox_models.c 9,553
|
||||
source/rasterizer/xbox/rasterizer_xbox_shadows.c 1,616
|
||||
```
|
||||
|
||||
### Render — 8,286 bytes
|
||||
|
||||
```text
|
||||
source/render/render_cameras.c 4,649
|
||||
source/render/render_particles.c 1,154
|
||||
source/render/render_sprite.c 2,483
|
||||
```
|
||||
|
||||
The arithmetic total for the complete allowlist is **83,898 meaningful residual bytes**.
|
||||
|
||||
The files under `source/rasterizer/xbox/` listed above are Halo-owned Xbox renderer code and are explicitly in scope. Do not classify them as external merely because `xbox` appears in the path.
|
||||
|
||||
Everything else is out of scope:
|
||||
|
||||
- No Xbox SDK/XDK library objects.
|
||||
- No Bink, Direct3D, XAPI, libcmt, zlib, libtiff, or other vendor-library campaign work.
|
||||
- No AI, units, vehicles, networking, physics, effects, sound, game-state, or unrelated renderer files.
|
||||
- Do not modify another lane’s `.c` file to make one of your objects match.
|
||||
|
||||
Related genuine headers and narrowly necessary configuration entries may be changed only under the header/configuration policy below.
|
||||
|
||||
## 4. Required reading before assigning work
|
||||
|
||||
Read these files completely before editing:
|
||||
|
||||
```text
|
||||
docs/campaign_house_rules.md
|
||||
docs/matching_methodology.md
|
||||
docs/exact_match_acceleration_playbook.md
|
||||
docs/campaign_throughput_lessons.md
|
||||
docs/common_constants.md
|
||||
docs/assertions.md
|
||||
docs/user_source_reconstruction_map_20260906.md
|
||||
docs/fake_match_review.md
|
||||
tools/campaign/README.md
|
||||
docs/object_matching_logs/opus5_next150_compiler_laws_20260916.md
|
||||
docs/object_matching_logs/opus5_next150_compiler_laws_round2_20260916.md
|
||||
docs/object_matching_logs/opus5_next150_research_campaign_20260916.md
|
||||
```
|
||||
|
||||
Then search and read every relevant current ledger before touching a function:
|
||||
|
||||
```text
|
||||
docs/object_matching_logs/astra_90pct_*
|
||||
docs/object_matching_logs/*bitmap*
|
||||
docs/object_matching_logs/*hud*
|
||||
docs/object_matching_logs/*interface*
|
||||
docs/object_matching_logs/*widget*
|
||||
docs/object_matching_logs/*motion_sensor*
|
||||
docs/object_matching_logs/*rasterizer*
|
||||
docs/object_matching_logs/*render_camera*
|
||||
docs/object_matching_logs/*render_particle*
|
||||
docs/object_matching_logs/*render_sprite*
|
||||
config/parked.json
|
||||
config/symbols.json
|
||||
```
|
||||
|
||||
Use `rg` by exact unit and function name. Do not rely on filenames alone. Newer Astra ledgers supersede older guesses when they contain fresh measurements, but every candidate must still be remeasured against commit `6130661c`.
|
||||
|
||||
Before assigning a function to a worker, run the existing unclassified/ledger cross-reference workflow described in the compiler-law documents. Determine:
|
||||
|
||||
1. Is it already exact at this baseline?
|
||||
2. Is the same source already integrated under another name?
|
||||
3. Was the proposed shape already tried?
|
||||
4. Is it parked, and what is the explicit reopen criterion?
|
||||
5. Is there a historical branch with a stronger body?
|
||||
6. Is the mismatch structural, relocation/ownership, frame/type, helper-boundary, x87 ordinal, or a proven allocator/scheduling tie?
|
||||
|
||||
Do not duplicate prior work merely because an old handoff started from a lower byte total.
|
||||
|
||||
## 5. Evidence hierarchy and research assets
|
||||
|
||||
Use evidence in this order:
|
||||
|
||||
1. January target object bytes, relocations, section ownership, public symbols, strings, callers, and callees.
|
||||
2. Authentic Bungie source or authenticated same-function cross-build source.
|
||||
3. Earlier/later Halo builds for semantics, names, types, and control-flow hypotheses.
|
||||
4. Open-source Marathon for Bungie style and likely abstractions.
|
||||
5. Compiler micro-labs and corpus-wide laws for source-shape discrimination.
|
||||
6. Pure visual similarity or decompiler output only as a hypothesis.
|
||||
|
||||
Relevant local evidence includes:
|
||||
|
||||
```text
|
||||
C:\Users\isabe\Downloads\Halo Combat Evolved (Jan 14, 2002 prototype)
|
||||
C:\Users\isabe\Downloads\Halo - Combat Evolved (Oct 12, 2001 prototype)\Halo 2276
|
||||
C:\Users\isabe\Downloads\haloleak2024\halo1
|
||||
C:\Users\isabe\Downloads\haloleak2024\halo1\h1_tags
|
||||
C:\Users\isabe\Documents\Codex\2026-07-13\i-w\_research-marathon-source-agent-20260904
|
||||
C:\Users\isabe\Documents\Codex\2026-07-13\i-w\_research-punpck-halo
|
||||
C:\Users\isabe\Documents\Codex\2026-07-13\i-w\_research-stian-halo
|
||||
C:\Users\isabe\Documents\Codex\2026-07-13\i-w\_research-halopc-restored
|
||||
C:\Users\isabe\Documents\Codex\2026-07-13\i-w\_research-demon
|
||||
C:\Users\isabe\Documents\Codex\2026-07-13\i-w\halocea-review
|
||||
C:\Users\isabe\Documents\Codex\2026-07-13\i-w\research
|
||||
C:\Users\isabe\Documents\Codex\2026-07-13\i-w\research-cache
|
||||
C:\Users\isabe\Documents\Codex\2026-07-13\i-w\_research_cache
|
||||
```
|
||||
|
||||
Known limitations:
|
||||
|
||||
- The January `cachebeta.pdb` has useful public symbols but lacks Halo locals and line records.
|
||||
- The supplied 2020 symbol executables have confirmed source differences. Use them for names, types, and semantic hypotheses—not January byte proof.
|
||||
- Use both IDA and Ghidra evidence where available. IDA Free on this machine has no usable headless scripting/RPC interface; do not burn a wave repeatedly trying to automate it. Use an existing interactive IDA database/export if available, and use Ghidra headless plus DIA/public-symbol tooling for repeatable extraction.
|
||||
- Never execute supplied game/tool binaries merely to inspect them.
|
||||
- Decompiler pseudocode is not original source.
|
||||
|
||||
When existing evidence is insufficient, research the target rather than declaring human-written code impossible. Build caller/callee graphs, inspect data and relocation ownership, compare cross-build implementations, search authentic source idioms, and construct narrowly controlled compiler labs. Validate any new “compiler law” against exact controls before applying it.
|
||||
|
||||
## 6. House rules — mandatory
|
||||
|
||||
1. Format a no-argument parameter list with `void` on its own line inside the parentheses.
|
||||
2. Put every parameter on its own line.
|
||||
3. End every function—including `void` functions—with an explicit `return;`. Non-void functions must return an appropriate value, never a bare `return;`.
|
||||
4. Use subsystem macros wrapping `tag_get` for typed tag access.
|
||||
5. Use typed object-access macros rather than repeated casts after raw `object_get` calls.
|
||||
6. Preserve the January inline schedule without emitting a `point_from_line3d` COMDAT.
|
||||
7. Name private functions correctly. Never introduce `code_XXXXXXXX`, `sub_XXXXXXXX`, or address-based private names.
|
||||
8. Name globals correctly. Never introduce `bss_XXXXXXXX` or address-based names. When the original name is unavailable, use a descriptive name consistent with project conventions and label it as inferred.
|
||||
9. Put function prototypes in their genuine owner headers or genuine TU-private location, never in an unrelated consumer `.c` file.
|
||||
10. Helper and math functions may use inline assembly only sparingly and with direct evidence. Existing admitted asm is not blanket precedent for new asm.
|
||||
11. If easy exactness is not achievable, retain the best credible fuzzy reconstruction, document and park it, and grant it zero exact credit.
|
||||
12. Prioritize small functions and near-complete objects within this assigned family, while still researching the larger structural functions.
|
||||
13. Avoid forced/manual inlining. Preserve natural helpers and January’s observed inline schedule.
|
||||
14. Use open-source Marathon as a style and semantic reference, not proof of January bytes.
|
||||
15. If a `.c` file has no dedicated header, use the closest genuine associated header.
|
||||
16. Use proper enum constants in switch tables, not unexplained raw case numbers.
|
||||
17. Declare and initialize variables together when practical and natural.
|
||||
18. Prefer established `cseries.h` macros over manual bit manipulation.
|
||||
19. Use project-defined types such as `real`, `boolean`, `byte`, `word`, and `dword` rather than generic substitutes such as `float`, C++ `bool`, or platform-dependent integers.
|
||||
20. Reject fake matching and source that Bungie almost certainly would not have written.
|
||||
21. Reject nonsensical function logic even if it coincidentally byte-matches.
|
||||
22. Use `/QIfist` only where target/compiler evidence requires it. It is a per-TU option, not a blanket setting.
|
||||
|
||||
Additional fidelity requirements:
|
||||
|
||||
- Use `assert(expression)`, `dassert(expression, diagnostic)`, and `vassert(expression, format, ...)` through the established `cseries.h` owner. Likewise use the established `warn`/`dwarn`/`vwarn` and `halt`/`dhalt`/`vhalt` families. Do not hand-expand them into `display_assert`, formatting buffers, and `system_exit`.
|
||||
- Assertion predicates state the required invariant. Do not accidentally invert them.
|
||||
- Preserve evaluation count, evaluation order, and lazy diagnostics.
|
||||
- No `volatile`, `register`, dummy statements, dead locals, arbitrary buffer inflation, invented globals, compiler barriers, pragmas, raw byte emission, self-assignments, empty branches, goto-next-label tricks, or duplicated equivalent branches merely to steer code generation.
|
||||
- No undefined behavior, uninitialized reads, out-of-bounds accesses, inactive-union-member tricks, representation-punning casts, raw numeric struct offsets, or stack overruns for a match. If January appears to contain a genuine bug, document the evidence and hold it for an owner ruling; do not silently land it.
|
||||
- Do not extend function-specific prior rulings to other functions.
|
||||
- Correct semantics and credible source are admission requirements even when bytes match.
|
||||
|
||||
## 7. Strict exactness, fuzzy work, and accounting
|
||||
|
||||
A function is strict exact only when the established comparator proves:
|
||||
|
||||
- exact function size,
|
||||
- exact normalized code bytes,
|
||||
- exact relocation count,
|
||||
- exact relocation addresses/types,
|
||||
- exact relocation target identities,
|
||||
- and the correct target-function owner.
|
||||
|
||||
Do not call a size/relocation near-tie exact. Do not use semantic overrides or matching allowlists to manufacture credit.
|
||||
|
||||
Maintain three separate totals:
|
||||
|
||||
1. Newly strict **meaningful** code bytes from `build/semantic_report.json`.
|
||||
2. Newly strict padded/function-section bytes from the stable verdict diff.
|
||||
3. Credible fuzzy bytes retained at **zero credit**.
|
||||
|
||||
Also report:
|
||||
|
||||
- strict functions gained,
|
||||
- strict functions lost,
|
||||
- newly complete function-only objects,
|
||||
- newly admitted whole `Matching` objects,
|
||||
- data/BSS/linkage/extra-owner changes,
|
||||
- parks removed, remeasured, stale, or invalid.
|
||||
|
||||
A function-only 100% object is not automatically a whole matching object. Before marking an object `Matching`, prove:
|
||||
|
||||
- every required Halo function is strict exact,
|
||||
- data, rdata, BSS, and COMMON ownership agree,
|
||||
- linkage/storage classes agree,
|
||||
- no extra code or data owner is emitted,
|
||||
- helper/COMDAT ownership agrees with January,
|
||||
- the object is source-authentic,
|
||||
- and the object-admission audit accepts it.
|
||||
|
||||
A blue “100%” result is not green whole-object proof. Halo-owned Xbox rasterizer objects must not be hidden as `external`.
|
||||
|
||||
Never trade away an inherited exact function. Gross gain does not conceal a regression. If an intentional exactness loss is ever proposed, do not land it without an explicit owner ruling and explicit subtraction from the totals.
|
||||
|
||||
## 8. Anti-duplication procedure
|
||||
|
||||
Before editing each unit:
|
||||
|
||||
```text
|
||||
git log --all -- <unit.c>
|
||||
python tools/campaign/branch_sweep.py <unit-without-.c>
|
||||
python tools/campaign/gate.py <unit-without-.c> --all
|
||||
python -m tools.campaign.unparked <unit-without-.c>
|
||||
```
|
||||
|
||||
Search the function and unit name across all ledgers and handoffs. Map any promising historical blob back to its commits and provenance. A historical exact body still needs current-baseline source, owner, ABI, house-rule, and regression review.
|
||||
|
||||
Never count:
|
||||
|
||||
- code already exact at `6130661c`,
|
||||
- code newly exact only because of a symbol alias without authenticated naming evidence,
|
||||
- a donor’s claimed total,
|
||||
- a function that another worker landed earlier in this lane,
|
||||
- helper code not owned by the January object,
|
||||
- or fuzzy code.
|
||||
|
||||
Keep a central assignment ledger so two workers never attack the same TU or function.
|
||||
|
||||
Historical leads such as `_bitmap_2d_sharpen`, `_bitmap_group_add_bitmap`, `_EncodeBlockRGBColorKey`, `_first_person_weapon_update`, `_hud_render_unit_interface`, `_hud_update_weapon`, motion-sensor updates, environment/lightmap/fog functions, and render-camera frustum functions must be remeasured. Their old labels are hypotheses, not instructions. Do not repeat a recorded negative shape unless new evidence directly refutes the old premise.
|
||||
|
||||
## 9. Parallel campaign architecture
|
||||
|
||||
Use agents aggressively, but safely:
|
||||
|
||||
- One implementation worker per `.c` file.
|
||||
- Files must be strictly disjoint.
|
||||
- No worker edits headers, config, shared docs, or another worker’s file.
|
||||
- Workers use `tools/campaign/gate.py`, which writes PID-isolated scratch objects.
|
||||
- Workers do not run `ninja`, `configure.py`, or any command that writes the shared `build/` tree.
|
||||
- Workers do not commit.
|
||||
- Workers record the exact current unit census before editing.
|
||||
- Workers retain only source-authentic improvements and fully revert reductions in strict exactness.
|
||||
- Each landed file receives an independent adversarial review by an agent other than its author.
|
||||
- Only the orchestrator edits genuine shared headers/config, runs full builds, updates parks, and commits.
|
||||
|
||||
Use waves of disjoint TUs. Start with:
|
||||
|
||||
1. Unwritten functions.
|
||||
2. Small functions capable of closing near-complete objects.
|
||||
3. Structural mismatches with a named source-level defect.
|
||||
4. Larger functions where call graph, frame, type width, relocation, or helper-boundary evidence gives a concrete route.
|
||||
5. Pure allocation/x87/scheduling ties only when a new evidenced compiler law supplies a legitimate source lever.
|
||||
|
||||
Eight small closures are preferable to one speculative rewrite. However, do not abandon large objects forever: give their biggest functions dedicated research packets after the easy structural pool is harvested.
|
||||
|
||||
If a wave yields little, preserve its durable negative evidence and immediately pivot to a different mechanism. Do not spend multiple waves permuting declarations or random spellings.
|
||||
|
||||
## 10. Existing tools — use universal gates
|
||||
|
||||
Prefer the committed campaign tools over writing a bespoke Python test for every function:
|
||||
|
||||
```text
|
||||
python tools/campaign/board.py
|
||||
python tools/campaign/board.py <unit>
|
||||
python tools/campaign/gate.py <unit> --fn <function>
|
||||
python tools/campaign/gate.py <unit> --all
|
||||
python tools/campaign/alndiff.py <unit> <function>
|
||||
python tools/campaign/relocdiff.py <unit> <function> --count-by-target
|
||||
python tools/campaign/tinfo.py <unit> --fn <function>
|
||||
python tools/campaign/tinfo.py <unit> --data
|
||||
python tools/campaign/branch_sweep.py <unit>
|
||||
python tools/bijection_walk.py --unit <unit> <function> -v
|
||||
python tools/fake_match_scan.py <changed paths>
|
||||
python -m tools.campaign.unparked <unit>
|
||||
python -m tools.campaign.stable_verdicts snapshot <file>
|
||||
python -m tools.campaign.stable_verdicts diff <before> <after>
|
||||
python -m tools.parked_functions
|
||||
python -m tools.audit_semantic_matches
|
||||
python tools/audit_object_admission.py
|
||||
```
|
||||
|
||||
Use `alndiff.py`, not `gate.py --disas`, when instruction counts diverge; the latter is an index-aligned zip and hides insert/delete boundaries.
|
||||
|
||||
Use the existing frame-slot, x87-mod8, inline-boundary, cross-jump, scheduling-selection, and unclassified-triage detectors described in the compiler-law ledgers. Run their required ordering before inventing source shapes.
|
||||
|
||||
Spelling sweeps and compiler probes are diagnostic only. A winning spelling is not source-authenticity evidence by itself.
|
||||
|
||||
Do not add general tooling unless it solves a genuinely recurring gap. Any committed tool must be tested and documented; otherwise keep research scripts under untracked scratch evidence.
|
||||
|
||||
## 11. Headers and configuration
|
||||
|
||||
Header changes are high-risk because VC7 code generation is definition-position sensitive.
|
||||
|
||||
To keep the four concurrent lanes mechanically reconcilable, do not commit
|
||||
changes to broad cross-lane headers such as `cseries.h`, `real_math.h`, core
|
||||
object/tag headers, or a header genuinely owned by another lane. Preserve any
|
||||
such requirement as a minimal proposed patch with consumer census and strict
|
||||
before/after evidence, then continue elsewhere. Lane C may commit only genuine
|
||||
bitmap, interface, rasterizer, or render owner-header changes whose complete
|
||||
consumer set has been audited under the protocol below.
|
||||
|
||||
Before changing any header:
|
||||
|
||||
1. Identify every `.c` includer with `rg`.
|
||||
2. Prove the declaration belongs in that header.
|
||||
3. Determine whether a TU-private declaration is more authentic.
|
||||
4. Compile pristine and patched header trees for every dependent TU.
|
||||
5. Compare every dependent function’s size, relocations, normalized hash, emitted owners, and data ownership.
|
||||
6. Run a full stable whole-tree diff.
|
||||
7. Obtain an independent reviewer’s approval.
|
||||
8. Commit the header prerequisite in an independently buildable packet.
|
||||
|
||||
Do not keep a header change that gains your object by regressing an unrelated object. Do not “repair” a regression with coincidental declaration ordering.
|
||||
|
||||
Configuration policy:
|
||||
|
||||
- `config/symbols.json`: edit only with authenticated January/PDB/source/caller evidence. Keep a symbol rename and the corresponding source identifiers in the same coherent commit.
|
||||
- `config/parked.json`: orchestrator only. Remove a park when the function is newly exact. Rebaseline a credible fuzzy function only with fresh measurements and dated evidence. Never rebaseline a park to conceal a regression.
|
||||
- `config/config.json` or object `Matching` status: change only after whole-object admission proves code, data, BSS, linkage, extra-owner, and source credibility.
|
||||
- Never add a semantic-match override.
|
||||
- Never broadly change compiler flags. `/QIfist` requires per-TU proof and full consumer/caller verification.
|
||||
|
||||
If a required owner header is shared with an out-of-scope unit, you may make the minimal genuine header change but may not edit the out-of-scope `.c` file. Every consumer must remain exact or unchanged.
|
||||
|
||||
## 12. COMDAT, owner, and inline safeguards
|
||||
|
||||
For every changed TU:
|
||||
|
||||
```text
|
||||
python tools/campaign/gate.py <unit> --forbid-emitted-symbol _point_from_line3d --all
|
||||
```
|
||||
|
||||
This must explicitly pass. Undefined references do not fail the guard; a candidate code definition does.
|
||||
|
||||
Also inspect:
|
||||
|
||||
- target and candidate code-symbol owner sets,
|
||||
- COMDAT selection and storage class,
|
||||
- helper bodies emitted only by the candidate,
|
||||
- missing target helper owners,
|
||||
- data/rdata/BSS/COMMON owners,
|
||||
- relocation target identity and addends,
|
||||
- private versus external linkage.
|
||||
|
||||
Do not gain a caller by changing the wrong helper owner. Preserve January’s observed inline schedule. Do not make shared `real_math.h` inline bodies `static` or otherwise globally change helper emission to fix one object.
|
||||
|
||||
Existing admitted asm such as `fast_ftol` or the already-reviewed color helper is function-specific evidence. It is not permission to hand-write arbitrary renderer bodies in assembly.
|
||||
|
||||
## 13. Baseline, checkpoint, and final verification
|
||||
|
||||
Before editing:
|
||||
|
||||
1. Run the full build.
|
||||
2. Save a stable verdict snapshot.
|
||||
3. Save `build/semantic_report.json`.
|
||||
4. Record board totals and all in-scope per-unit gates.
|
||||
5. Validate parks and object admission.
|
||||
6. Record the baseline owner/data census for every assigned object.
|
||||
|
||||
At each coherent admission batch:
|
||||
|
||||
1. Review the source diff for house-rule compliance.
|
||||
2. Run each changed unit’s full `gate.py --all`.
|
||||
3. Run the `_point_from_line3d` emitted-symbol guard.
|
||||
4. Review every target/candidate owner and relocation change.
|
||||
5. Run the fake-match scanner over all changed source.
|
||||
6. Run `ninja`.
|
||||
7. Take a fresh stable snapshot and diff it from the frozen baseline and the previous checkpoint.
|
||||
8. Require zero inherited exact regressions.
|
||||
9. Validate parks.
|
||||
10. Run semantic-match and whole-object admission audits.
|
||||
11. Run the repository’s full pytest suite.
|
||||
12. Run `git diff --check`.
|
||||
13. Commit only when the tree is fully verified.
|
||||
|
||||
At final tip, require:
|
||||
|
||||
```text
|
||||
ninja
|
||||
python -m tools.campaign.stable_verdicts snapshot scratch/lane-c-after.json
|
||||
python -m tools.campaign.stable_verdicts diff scratch/lane-c-before.json scratch/lane-c-after.json
|
||||
python -m tools.parked_functions
|
||||
python -m tools.audit_semantic_matches
|
||||
python tools/audit_object_admission.py
|
||||
python tools/fake_match_scan.py <all changed source/header paths>
|
||||
python -m pytest -q
|
||||
git diff --check
|
||||
git status --short
|
||||
```
|
||||
|
||||
If scratch content interferes with pytest discovery, move evidence outside the worktree rather than excluding real tests.
|
||||
|
||||
The final tracked tree must be clean. Keep bulky scratch objects and experimental variants outside Git.
|
||||
|
||||
## 14. Fuzzy preservation
|
||||
|
||||
If a credible reconstruction is the best current implementation but does not become strict exact:
|
||||
|
||||
- Keep it only if semantics, ABI, ownership, and house rules are sound.
|
||||
- Measure size, normalized divergence, relocations, and first differing regions.
|
||||
- Compare it with the baseline and every known donor.
|
||||
- Document why it is better.
|
||||
- Record remaining blockers and exact reopen criteria.
|
||||
- Update its park evidence honestly.
|
||||
- Give it zero strict credit.
|
||||
- Do not sacrifice an exact sibling or whole-object owner to retain it.
|
||||
|
||||
A fuzzy implementation is useful future research, but it must never inflate the strict total.
|
||||
|
||||
## 15. Campaign behavior
|
||||
|
||||
Work autonomously. Do not pause for ordinary implementation questions. If one function needs an owner ruling, park that question, continue unrelated work, and present rulings in a compact batch.
|
||||
|
||||
Do not terminate because:
|
||||
|
||||
- the first wave was low yield,
|
||||
- a previous ledger called something difficult,
|
||||
- a function is parked,
|
||||
- a header is shared,
|
||||
- or the PDB lacks locals.
|
||||
|
||||
Instead, determine whether new evidence can satisfy the reopen condition. Conversely, do not repeatedly attack a proven allocator tie without a new source-level lever.
|
||||
|
||||
Every one of the 83,898 starting residual bytes must finish in one of these categories:
|
||||
|
||||
1. Strict exact and landed.
|
||||
2. Credible fuzzy improvement landed at zero credit.
|
||||
3. Evidence-backed structural blocker with a concrete reopen criterion.
|
||||
4. Demonstrated compiler allocation/scheduling tie with the validating detector.
|
||||
5. Owner/policy ruling required, with a minimal ready candidate.
|
||||
6. Previously solved/duplicate at the frozen baseline and therefore excluded from new credit.
|
||||
|
||||
“Unexamined” is not an acceptable final category.
|
||||
|
||||
## 16. Commit and handoff requirements
|
||||
|
||||
Make small, independently buildable commits organized by coherent TU or owner packet. Avoid a tangled final megacommit. Header/config prerequisites and their affected source must remain in a clear, ordered series.
|
||||
|
||||
Do not push.
|
||||
|
||||
Create:
|
||||
|
||||
```text
|
||||
docs/object_matching_logs/claude_lane_c_graphics_ui_HANDOFF_20260920.md
|
||||
docs/object_matching_logs/claude_lane_c_graphics_ui_admission_manifest_20260920.json
|
||||
```
|
||||
|
||||
The handoff must include:
|
||||
|
||||
- frozen base and final commit IDs,
|
||||
- exact reverse-order cherry-pick range,
|
||||
- every commit and changed file,
|
||||
- baseline and final strict functions,
|
||||
- baseline and final meaningful exact bytes,
|
||||
- new meaningful bytes,
|
||||
- new padded bytes,
|
||||
- fuzzy bytes at zero credit,
|
||||
- exact regressions, which must be zero,
|
||||
- objects moved to function-only 100%,
|
||||
- objects admitted as whole `Matching`,
|
||||
- data/BSS/linkage/COMDAT owner changes,
|
||||
- header/config changes and their full blast-radius evidence,
|
||||
- parks removed or remeasured,
|
||||
- tests and audits with exact counts,
|
||||
- fake-scan findings and disposition,
|
||||
- per-function sizes, hashes, relocation counts, and source evidence,
|
||||
- rejected experiments and do-not-repeat findings,
|
||||
- unresolved candidates and precise reopen criteria,
|
||||
- confirmation that canonical was untouched and nothing was pushed.
|
||||
|
||||
The JSON manifest must be machine-readable and contain per-function before/after evidence, not merely headline totals.
|
||||
|
||||
Finish with a clean local branch and report:
|
||||
|
||||
```text
|
||||
branch
|
||||
base
|
||||
tip
|
||||
commit count
|
||||
strict meaningful gain
|
||||
strict padded gain
|
||||
strict function gain
|
||||
whole-object Matching gain
|
||||
fuzzy bytes retained at zero credit
|
||||
regressions
|
||||
test/audit results
|
||||
git status
|
||||
nothing pushed
|
||||
canonical untouched
|
||||
```
|
||||
@@ -1,77 +0,0 @@
|
||||
# Claude Lane D — refreshed after A/B/C reconciliation
|
||||
|
||||
Work on Halo January 2342 **Halo-owned** code, not Xbox/vendor libraries. Start
|
||||
an isolated local worktree and branch at the **latest fetched tip** of
|
||||
`jonas/exact-pilots` (`https://github.com/bnunu/halo`). Verify that this tip
|
||||
contains the audited A/B/C reconciliation commit
|
||||
`4f4c85021db48dae61252d8e1301c60e1c2cc138`, record its full hash in
|
||||
your handoff, and confirm a clean tree before editing. Do not start from the
|
||||
stale `6130661c` base in the old Lane D brief. Never modify canonical or
|
||||
push your lane.
|
||||
|
||||
Read these complete before selecting work:
|
||||
|
||||
- `docs/campaign_prompts/CLAUDE_REMAINING_LANE_D_SYSTEMS_EFFECTS_20260920.md`
|
||||
for the full 49-TU Lane D allowlist, reference paths, workflow and house rules;
|
||||
**this refresh overrides its baseline, numeric portfolio, cross-lane header
|
||||
reservations, and absolute COMDAT rule**.
|
||||
- `docs/campaign_house_rules.md`, `docs/matching_methodology.md`,
|
||||
`docs/common_constants.md`, `docs/assertions.md`,
|
||||
`docs/campaign_throughput_lessons.md`.
|
||||
- `docs/object_matching_logs/claude_lane_a_ai_core_HANDOFF_20260920.md`,
|
||||
`docs/object_matching_logs/claude_lane_a_HANDOFF_TO_LANE_B_20260921.md`,
|
||||
`docs/object_matching_logs/claude_lane_b_HANDOFF_20260920.md`,
|
||||
`docs/object_matching_logs/claude_lane_b_rejected_hypotheses_20260920.md`,
|
||||
`docs/object_matching_logs/claude_lane_c_canonical_reconciliation_20260922.md`,
|
||||
and `docs/common_pool_ordering_20260922.md`.
|
||||
|
||||
Re-measure the allowlist against **this** baseline. A/B/C already changed some
|
||||
Lane D files, so no old residual size, park count, donor gain, or archived lane
|
||||
report is current authority. Freeze a stable-verdict snapshot, per-object
|
||||
function/data/owner census, parks, admission audit, build and tests before any
|
||||
edit. Prioritize still-unwritten and structural gaps in projectiles/weapons,
|
||||
decals/effects, HS compile/runtime, sound, geometry, and the smaller systems
|
||||
objects; do not redo already exact rows. Aim for 40K new meaningful exact code
|
||||
bytes while evidence supports it, but report the actual verified delta only.
|
||||
|
||||
Lessons that bind this lane:
|
||||
|
||||
1. Exact function credit requires a strict stable row, full build, unchanged
|
||||
inherited exact rows, sound semantics, and an ownership audit. A fuzzy body
|
||||
is useful source but earns zero exact bytes. Data scoring changed with
|
||||
objdiff v3.6.0; separate scorer/accounting gains from newly reconstructed
|
||||
source and keep `linker_common` at zero credit while incomplete.
|
||||
2. Header definition position can alter unrelated TUs. Put each genuine owner
|
||||
header change in a prerequisite commit, enumerate all consumers, and run a
|
||||
board-wide per-row sweep. Do not hide a needed declaration in a consumer
|
||||
`.c`. The A/B/C work has landed, so prior cross-lane reservations are lifted;
|
||||
the blast-radius rule is not.
|
||||
3. COMMON pool adjacency is only a negative constraint, **never** proof of a
|
||||
global's owning TU. Do not add unreferenced or address-named globals to
|
||||
complete `.data`/`.bss`. Require an independent original owner/type oracle.
|
||||
4. A real shared-header inline COMDAT may be emitted under the documented
|
||||
A/B/C narrow exception only when January's folded copy is byte-identical,
|
||||
the caller is strict exact, the full owner census is reviewed, and no exact
|
||||
sibling regresses. Do not hand-expand helpers to evade ownership. In
|
||||
particular, preserve the January `_point_from_line3d` schedule.
|
||||
5. Previously held UB, artificial duplicate work, pragmas, two-pass asm, and
|
||||
source-shape steering do **not** become acceptable merely because they
|
||||
byte-match. Reopen only on new primary evidence and an explicit owner
|
||||
ruling. The rejected Lane C COMMON, null-write, HUD asm/pragma, and
|
||||
lens-flare-overrun packets are examples, not backlog to re-land.
|
||||
6. Use first-party January bytes/relocations, January MAP/PDB, the supplied
|
||||
Bungie C files, HCEA/2020, Ghidra/DIA and Marathon with their correct
|
||||
evidentiary limits. The later builds are not interchangeable with January.
|
||||
Do not spend a wave on known pure register/x87 ties without a falsifiable
|
||||
source, type or header hypothesis.
|
||||
|
||||
Use one worker per disjoint `.c`; workers use PID-isolated `gate.py` scratch
|
||||
objects, never shared build/config. Orchestrator alone edits headers/config,
|
||||
runs Ninja, performs the stable diff, commits, and updates parks. In each
|
||||
5K–15K wave reject exact losses, invalid parks, invented owners, surplus
|
||||
COMDATs, fake-scan leads, and nonsensical logic before banking. Keep a
|
||||
machine-readable per-function manifest and an evidence-backed list of rejected
|
||||
trials. End with local commits, a clean worktree, final tests/build/sweep and
|
||||
handoff; **do not push**. Report strict meaningful code, padded code, fuzzy
|
||||
zero-credit extent, data-only/scorer gains and whole-object completions
|
||||
separately.
|
||||
@@ -1,311 +0,0 @@
|
||||
# Claude prompt — Lane D: effects, items, world data, sound, scripting, and systems
|
||||
|
||||
You are running one of four strictly disjoint Halo 1 January 2342 exact-match
|
||||
lanes. Work aggressively and persistently, but never purchase byte equality
|
||||
with fake source, undefined behavior, invented ownership, target rewriting, or
|
||||
nonsensical logic.
|
||||
|
||||
## Fixed baseline and isolation
|
||||
|
||||
- Repository: https://github.com/bnunu/halo
|
||||
- Baseline branch: jonas/exact-pilots
|
||||
- Exact baseline commit: `6130661c9585fdb2785b3ff6bdb2ad0cfef0520c`
|
||||
(Reconcile final Astra campaign, +4,073 bytes)
|
||||
- Create an isolated worktree and branch from that exact commit, for example
|
||||
C:\\halo-worktrees\\claude-remaining-lane-d-20260920 on
|
||||
claude/remaining-lane-d-20260920.
|
||||
- Confirm `git rev-parse HEAD` equals the full baseline hash and the tree is
|
||||
clean.
|
||||
- Never edit the canonical checkout. Never push. Do not merge or rebase another
|
||||
campaign. Finish with local commits and a clean worktree.
|
||||
- Read the whole repository and evidence corpus, but modify only Lane D files,
|
||||
genuine Lane D owner headers after the header protocol below, uniquely named
|
||||
Lane D documentation, and a final isolated bookkeeping commit.
|
||||
|
||||
The reconciled baseline has 1,443,979 / 1,770,166 accepted Halo meaningful
|
||||
bytes (81.573084%), 7,291 / 7,574 accepted Halo functions, and 184 valid active
|
||||
parks. All four lanes together cover 326,187 remaining Halo-owned bytes.
|
||||
|
||||
Lane D owns 87,255 meaningful residual bytes across 49 translation units:
|
||||
32,593 written-unparked, 54,651 parked, and 11 unwritten. Target at least
|
||||
40,000 new strict meaningful bytes, with a stretch goal of closing the full
|
||||
portfolio. If 40K is not reached, continue until every unit has a verified
|
||||
landing or a precise evidence-backed blocker. Do not declare the lane
|
||||
unreachable from aggregate park counts.
|
||||
|
||||
## Exclusive Lane D allowlist
|
||||
|
||||
Only these translation units are in scope:
|
||||
|
||||
~~~text
|
||||
source/bink/bink_playback 979
|
||||
source/bungie_net/common/prime_numbers 340
|
||||
source/bungie_net/network/transport_endpoint_set_winsock 1344
|
||||
source/bungie_net/network/transport_endpoint_winsock 294
|
||||
source/cache/cache_files_decompress_windows 2117
|
||||
source/cache/cache_files_windows 746
|
||||
source/cache/xbox_sound_cache 368
|
||||
source/cache/xbox_texture_cache 209
|
||||
source/camera/dead_camera 1512
|
||||
source/camera/editor_flying_camera 2563
|
||||
source/camera/observer 1561
|
||||
source/cseries/profile 276
|
||||
source/cseries/stack_walk_windows 1167
|
||||
source/cutscene/cinematics 1272
|
||||
source/effects/contrails 945
|
||||
source/effects/decals 7930
|
||||
source/effects/effects 3003
|
||||
source/effects/particle_systems 2103
|
||||
source/effects/player_effects 2355
|
||||
source/effects/weather_particle_systems 2346
|
||||
source/hs/hs 81
|
||||
source/hs/hs_compile 2632
|
||||
source/hs/hs_runtime 3404
|
||||
source/items/items 2352
|
||||
source/items/projectiles 7905
|
||||
source/items/weapons 2224
|
||||
source/main/main 2542
|
||||
source/math/geometry 4775
|
||||
source/math/periodic_functions 244
|
||||
source/networking/network_connection 588
|
||||
source/objects/damage 2663
|
||||
source/objects/widgets/flags 1170
|
||||
source/objects/widgets/glow 1729
|
||||
source/objects/widgets/light_volumes 905
|
||||
source/objects/widgets/lightning 2571
|
||||
source/saved games/player_profile 1148
|
||||
source/saved games/saved_game_files 359
|
||||
source/sound/game_sound 1570
|
||||
source/sound/ima_adpcm 404
|
||||
source/sound/sound_dsound_xbox 630
|
||||
source/sound/sound_manager 3966
|
||||
source/structures/leaf_map 1950
|
||||
source/structures/structure_detail_objects 66
|
||||
source/structures/structure_lens_flares 4331
|
||||
source/structures/structure_visibility 468
|
||||
source/structures/structures 1210
|
||||
source/tag_files/files_windows 209
|
||||
source/text/draw_string 920
|
||||
source/tool/connected_geometry 809
|
||||
~~~
|
||||
|
||||
Numbers are current residual bytes, not promised gains. Do not work in libs/**,
|
||||
xbox/**, vendor Bink objects, libcmt, d3d8, d3dx8, dsound, xapi, xnet, xkbd, or
|
||||
any translation unit absent from the allowlist.
|
||||
|
||||
## Read before editing
|
||||
|
||||
Read these files completely:
|
||||
|
||||
~~~text
|
||||
README.md
|
||||
docs/campaign_house_rules.md
|
||||
docs/matching_methodology.md
|
||||
docs/common_constants.md
|
||||
docs/assertions.md
|
||||
docs/campaign_throughput_lessons.md
|
||||
tools/campaign/README.md
|
||||
docs/object_matching_logs/astra_90pct_HANDOFF_20260920.md
|
||||
docs/object_matching_logs/astra_90pct_research_atlas_20260920.md
|
||||
docs/object_matching_logs/astra_90pct_rejected_hypotheses_20260920.md
|
||||
docs/object_matching_logs/astra_90pct_admission_manifest_20260920.json
|
||||
docs/object_matching_logs/astra_90pct_research5_shared_context_20260920.md
|
||||
docs/object_matching_logs/astra_90pct_research5_shared_schedule_20260920.md
|
||||
docs/object_matching_logs/astra_90pct_research5_projectiles_20260920.md
|
||||
docs/object_matching_logs/astra_90pct_research5_structure_lens_20260920.md
|
||||
docs/object_matching_logs/astra_90pct_research5_sound_type_rejected_20260920.md
|
||||
docs/object_matching_logs/astra_90pct_research8_damage_20260920.md
|
||||
docs/object_matching_logs/astra_90pct_research8_damage_independent_20260920.md
|
||||
docs/object_matching_logs/astra_90pct_research8_sound_listener_20260920.md
|
||||
docs/object_matching_logs/astra_90pct_research10_weapon_projectiles_20260920.md
|
||||
docs/object_matching_logs/astra_90pct_research10_weapon_projectiles_independent_20260920.md
|
||||
docs/object_matching_logs/astra_90pct_research12_weapons_tail_20260920.md
|
||||
docs/object_matching_logs/astra_90pct_research12_weapons_owner_independent_20260920.md
|
||||
docs/object_matching_logs/astra_90pct_wave4_decals_20260920.md
|
||||
docs/object_matching_logs/astra_90pct_wave4_decals_independent_review_20260920.md
|
||||
~~~
|
||||
|
||||
Search current per-object logs before reopening any park. Useful read-only
|
||||
primary and cross-build material:
|
||||
|
||||
~~~text
|
||||
C:\\Users\\isabe\\Downloads\\Halo Combat Evolved (Jan 14, 2002 prototype)
|
||||
C:\\Users\\isabe\\Downloads\\Halo - Combat Evolved (Oct 12, 2001 prototype)\\Halo 2276
|
||||
C:\\Users\\isabe\\Downloads\\haloleak2024\\halo1\\network_client_manager.c
|
||||
C:\\Users\\isabe\\Downloads\\haloleak2024\\halo1\\network_server_manager.c
|
||||
C:\\Users\\isabe\\Downloads\\haloleak2024\\halo1\\random_math.c
|
||||
C:\\Users\\isabe\\Downloads\\haloleak2024\\halo1\\h1_tags
|
||||
C:\\Users\\isabe\\Documents\\Codex\\2026-07-13\\i-w\\_research-marathon-source-agent-20260904
|
||||
C:\\Users\\isabe\\Documents\\Codex\\2026-09-20\\files-pasted-by-the-user-halo\\outputs\\astra_90pct_function_atlas.csv
|
||||
~~~
|
||||
|
||||
January's PDB has publics but no useful Halo locals or line records. The
|
||||
2020/debug executables have confirmed source differences. Use them as
|
||||
typed/control-flow evidence, not interchangeable source. IDA Free has no
|
||||
callable automation endpoint. Use Ghidra headless, DIA/PDB tools, January raw
|
||||
bytes and relocations, original MAP names, the supplied Bungie source, and
|
||||
authenticated cross-build windows.
|
||||
|
||||
## Mandatory house rules
|
||||
|
||||
1. Put void on its own line in every no-argument parameter list.
|
||||
2. Put every parameter on its own line.
|
||||
3. End every function with an explicit valid return.
|
||||
4. Use subsystem typed macros wrapping tag_get.
|
||||
5. Use typed object macros instead of raw object_get plus casts.
|
||||
6. Preserve January's inline schedule; emit no new point_from_line3d COMDAT.
|
||||
7. Give private functions authentic/descriptive names, never code plus address.
|
||||
8. Give globals authentic/descriptive names, never bss plus address.
|
||||
9. Put prototypes in genuine owners, not unrelated consumers.
|
||||
10. Use inline assembly only for evidenced low-level/helper/math instructions
|
||||
with no faithful VC7 C spelling.
|
||||
11. Retain and document credible fuzzy code at zero credit when easy exactness
|
||||
fails; park it for later.
|
||||
12. Prefer small closable functions before one giant residual.
|
||||
13. Do not force-inline or duplicate helper bodies to steer code generation.
|
||||
14. Marathon is style/semantic reference, not January byte proof.
|
||||
15. With no dedicated header, use the closest genuine associated header.
|
||||
16. Use named correct enum constants in switches.
|
||||
17. Declare and initialize variables together when practical.
|
||||
18. Prefer cseries.h macros over manual bit operations.
|
||||
19. Use project types such as real, boolean, byte, short, and long.
|
||||
20. Reject fake matching and implausible original source.
|
||||
21. Reject nonsensical logic even when bytes match.
|
||||
22. Use /QIfist only when target/compiler evidence requires it per TU and all
|
||||
affected callers/conversions have been audited.
|
||||
|
||||
Use the repository's verified assert/dassert/vassert, warn/dwarn/vwarn, and
|
||||
halt/dhalt/vhalt contracts from docs/assertions.md. Do not manually expand them.
|
||||
Preserve a target-proven original bug only when primary evidence is decisive,
|
||||
the semantics are documented with a BUG comment, and independent review agrees.
|
||||
Never introduce undefined behavior merely to shape bytes.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Establish the full baseline:
|
||||
|
||||
~~~text
|
||||
ninja -j4 all_source progress semantic_progress
|
||||
python -m pytest -q tools
|
||||
python -m tools.campaign.stable_verdicts snapshot scratch/lane-d-before.json
|
||||
python -m tools.parked_functions
|
||||
python tools/audit_object_admission.py --output scratch/lane-d-admission-before.json
|
||||
~~~
|
||||
|
||||
2. Build a Lane D ledger. For every row record meaningful and padded target
|
||||
size, candidate size, relocation count, normalized hash, objdiff percent,
|
||||
park class, reopen criterion, and prior experiments. Re-measure locally; the
|
||||
Astra CSV is routing evidence, not authority.
|
||||
|
||||
3. Attack in this order:
|
||||
- genuinely unwritten functions and missing coherent source graphs;
|
||||
- written-unparked structural differences involving calls, branches, fields,
|
||||
locals, types, or ownership;
|
||||
- small near-complete functions with new primary evidence;
|
||||
- parks only when evidence satisfies or refutes their reopen criteria.
|
||||
|
||||
Do not spend a wave on pure register allocation, independent-load ordering,
|
||||
or x87 stack ties without a falsifiable source/type/header hypothesis.
|
||||
|
||||
4. Highest leverage: projectiles and weapons; decals, structure lens flares,
|
||||
effects, particles and weather; HS compile/runtime; sound manager/game sound;
|
||||
geometry/math with natural helpers; then small cache, camera, object-widget,
|
||||
save, text and tool units. Use the three Bungie C files as style and semantic
|
||||
maps where applicable, not January byte authority.
|
||||
|
||||
5. Use PID-isolated scratch objects:
|
||||
|
||||
~~~text
|
||||
python tools/campaign/gate.py <unit> --fn <function> --out scratch/<unique>.obj
|
||||
python tools/campaign/alndiff.py <unit> <function> --ours-object scratch/<unique>.obj
|
||||
python tools/campaign/relocdiff.py <unit> <function> scratch/<unique>.obj --count-by-target
|
||||
python tools/campaign/tinfo.py --object scratch/<unique>.obj --data
|
||||
~~~
|
||||
|
||||
Use gate --edits or scratch source copies for bounded experiments. A gate hit is
|
||||
necessary but not sufficient: independently review semantics, source
|
||||
plausibility, relocations, owners, non-code sections, and siblings.
|
||||
|
||||
6. If using subagents, assign exactly one C file per worker. Workers use only
|
||||
gate.py and unique scratch objects; they do not run Ninja, edit headers or
|
||||
config, commit, or push. The orchestrator reproduces every hit.
|
||||
|
||||
7. Header protocol: edit only a genuine owner; enumerate every C consumer with
|
||||
rg first; freeze exact controls and owner/data/COMMON/COMDAT state; compile
|
||||
every consumer; put a header prerequisite in its own commit; reject any
|
||||
inherited exact loss or unsupported owner. If a required shared header is
|
||||
owned by another lane, preserve a proposed patch and evidence but do not
|
||||
edit it.
|
||||
|
||||
To minimize four-lane reconciliation, do not commit changes to broad
|
||||
cross-lane headers such as cseries.h, real_math.h, or core object/tag
|
||||
headers. Preserve those as separately reviewable proposed patches with a
|
||||
complete consumer census and strict before/after evidence. Commit only
|
||||
narrow genuine Lane D subsystem owner headers after the protocol above.
|
||||
|
||||
8. Shared config protocol: never change comparators, target objects, build
|
||||
metadata, global optimizer defaults, or semantic-credit rules. symbols.json
|
||||
requires original identity evidence. Matching requires full code, data, BSS,
|
||||
relocation, COMDAT, linkage, surplus-owner and source-authenticity audits.
|
||||
Keep source commits separate. Put minimal park changes in a final bookkeeping
|
||||
commit and duplicate the exact delta in the manifest for conflict-free
|
||||
integration.
|
||||
|
||||
9. Run the hard point_from_line3d emitted-symbol guard on every changed TU
|
||||
unless January genuinely owns it there. For inherited genuine owners, compare
|
||||
the complete before/after owner census. Reject surplus fast_ftol, pixel,
|
||||
math, or XDK helper owners unless authentic topology and link selection are
|
||||
proved. Equal bytes in another object are not ownership proof.
|
||||
|
||||
10. Preserve best credible fuzzy bodies only at zero credit. Do not count fuzzy
|
||||
target extent, objdiff percentage, or padded envelope as exact progress.
|
||||
|
||||
## Wave gates and accounting
|
||||
|
||||
Use coherent 5K–15K candidate waves. Before and after each landing, run full
|
||||
build and stable snapshots. At minimum:
|
||||
|
||||
~~~text
|
||||
ninja -j4 all_source progress semantic_progress
|
||||
python -m tools.campaign.stable_verdicts snapshot scratch/lane-d-after-N.json
|
||||
python -m tools.campaign.stable_verdicts diff scratch/lane-d-before-N.json scratch/lane-d-after-N.json
|
||||
python -m tools.parked_functions
|
||||
python tools/audit_object_admission.py --output scratch/lane-d-admission-N.json
|
||||
python tools/fake_match_scan.py --format json <changed files>
|
||||
git diff --check
|
||||
~~~
|
||||
|
||||
At each cumulative 10K meaningful checkpoint and final closeout also run the
|
||||
full tools tests and global fake scan. Audit exact bytes, ordered relocation
|
||||
identities, inherited matches, code/data/BSS/COMMON owners, COMDAT copies,
|
||||
externals, names/linkage, and non-code sections.
|
||||
|
||||
Report separately: strict meaningful bytes, strict padded bytes, and fuzzy
|
||||
target extent at zero credit. Never derive canonical gain from donor headlines.
|
||||
|
||||
## Commits and handoff
|
||||
|
||||
- Commit only independently verified packets, one coherent source/owner packet
|
||||
per commit. Header prerequisites precede source; park/config bookkeeping is
|
||||
last.
|
||||
- Do not add scratch, build outputs, binaries, PDB/MAP/EXE files, generated
|
||||
atlases, or large probe reports.
|
||||
- Use uniquely named Lane D records. End clean and do not push.
|
||||
|
||||
Create:
|
||||
|
||||
~~~text
|
||||
docs/object_matching_logs/claude_remaining_lane_d_HANDOFF_20260920.md
|
||||
docs/object_matching_logs/claude_remaining_lane_d_admission_manifest_20260920.json
|
||||
~~~
|
||||
|
||||
The handoff must state base/tip, ordered commits, changed files, per-function
|
||||
meaningful/padded bytes and fingerprints, strict gains, zero-credit fuzzy work,
|
||||
rejected trials, parks/config/header changes, owner/COMDAT/data results, exact
|
||||
commands/results, and blockers with concrete reopen criteria. The manifest must
|
||||
contain machine-readable measurements and exact proposed shared-config deltas.
|
||||
|
||||
Do not stop after a few easy leaves. Continue through the allowlist while
|
||||
tokens remain, switching quickly from exhausted scheduling ties to a different
|
||||
unit with structural evidence. Authenticity and zero regressions remain
|
||||
absolute under the 40K goal.
|
||||
@@ -1,25 +0,0 @@
|
||||
# Four-lane remaining-Halo campaign (2026-09-20)
|
||||
|
||||
These four self-contained Claude prompts partition every Halo-owned meaningful
|
||||
residual byte measured at canonical commit
|
||||
`6130661c9585fdb2785b3ff6bdb2ad0cfef0520c`. They deliberately exclude Xbox
|
||||
SDK/XDK and other vendor-library objects.
|
||||
|
||||
| Lane | Scope | Units | Residual bytes | Prompt |
|
||||
| --- | --- | ---: | ---: | --- |
|
||||
| A | AI core, actors, perception, communication, encounters | 11 | 79,657 | `CLAUDE_REMAINING_LANE_A_AI_CORE_20260920.md` |
|
||||
| B | AI actions/pathfinding, gameplay, physics/collision, units/vehicles | 31 | 75,377 | `CLAUDE_REMAINING_LANE_B_SIMULATION_PHYSICS_20260920.md` |
|
||||
| C | Bitmaps, UI/HUD, Halo-owned Xbox rasterizer, rendering | 30 | 83,898 | `CLAUDE_REMAINING_LANE_C_GRAPHICS_UI_20260920.md` |
|
||||
| D | Effects, items, scripting, sound, structures, systems | 49 | 87,255 | `CLAUDE_REMAINING_LANE_D_SYSTEMS_EFFECTS_20260920.md` |
|
||||
| **Total** | **All remaining Halo-owned code** | **121** | **326,187** | |
|
||||
|
||||
The translation-unit allowlists are mutually exclusive. Each prompt requires a
|
||||
dedicated worktree at the exact baseline, forbids pushes and canonical edits,
|
||||
requires current-state anti-duplication checks, applies all house rules, keeps
|
||||
fuzzy work at zero credit, and demands a clean machine-readable handoff for
|
||||
later reconciliation.
|
||||
|
||||
Run all four lanes in parallel only when each Claude session has its own
|
||||
worktree. Give each session exactly one prompt; do not combine the prompts or
|
||||
allow a lane to cross its allowlist. Canonical accounting remains authoritative
|
||||
over worker headline totals.
|
||||
@@ -1,218 +0,0 @@
|
||||
# Campaign throughput lessons (2026-08-30 / 2026-08-31)
|
||||
|
||||
Operational lessons from a run that took the board from **669,879 to 714,807
|
||||
matched bytes (+44,928)** and **4,829 to 4,973 credited functions (+144)** with
|
||||
**zero regressions**, verified by a full build plus a per-function sweep of all
|
||||
569 built units.
|
||||
|
||||
This document is about *throughput and hazards* - how to close many functions
|
||||
in parallel without breaking what already works. For per-function matching
|
||||
technique see `matching_methodology.md` and
|
||||
`exact_match_acceleration_playbook.md`.
|
||||
|
||||
---
|
||||
|
||||
## 1. Write unwritten functions before fighting residuals
|
||||
|
||||
This is the single highest-leverage finding. Measured across four waves:
|
||||
|
||||
| wave | scope | approach | bytes gained | yield |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | 71,112 B residual | close residuals | 11,040 | 16% |
|
||||
| 3 | 27,920 B "sha-only" residual | close residuals | 3,168 | 11% |
|
||||
| 4 | ~160,000 B unwritten | write missing functions | **30,720** | far larger scope |
|
||||
|
||||
Wave 3 deliberately picked the *closest* residuals on the board - functions
|
||||
whose padded size **and** relocation count already matched, so only instruction
|
||||
selection differed - and still returned only 11%. Those residuals are typically
|
||||
a single register-allocation or x87 stack-discipline decision, and they resist
|
||||
source-level control.
|
||||
|
||||
An **unwritten** function has no wrong prior to undo. You read the target
|
||||
disassembly and write natural C89. That is a fundamentally easier problem.
|
||||
|
||||
The board currently holds roughly **1,000,000 bytes of unwritten functions**
|
||||
against **100,000 bytes of residual**. Work the unwritten pool first.
|
||||
|
||||
Within a unit, start with the **small** functions. Eight 300-byte closures beat
|
||||
one failed heroic attempt at a 3,000-byte function.
|
||||
|
||||
## 2. Parallel fan-out architecture
|
||||
|
||||
`tools/campaign/gate.py <unit>` compiles **one** translation unit to a
|
||||
PID-named object under `scratch/` and never writes to `build/`. That makes it
|
||||
safe to run from many workers simultaneously.
|
||||
|
||||
The architecture that worked:
|
||||
|
||||
- **One worker per `.c` file, files strictly disjoint.** Never two workers in
|
||||
one file.
|
||||
- Every worker measures **only** with `gate.py`. Useful flags: `--fn <FUNC>`,
|
||||
`--disas <FUNC>`, `--source <FILE>` (compile a variant without touching the
|
||||
real file), `--edits <json>`.
|
||||
- **No worker runs `ninja` or `configure.py`.** A shared build directory cannot
|
||||
take concurrent writers.
|
||||
- **No worker commits.** The orchestrator does one full build, one board
|
||||
measurement, and one commit at the end.
|
||||
- Workers record `gate.py`'s exact count *before* starting and revert anything
|
||||
that lowers it.
|
||||
|
||||
### `--disas` hides insert/delete holes
|
||||
|
||||
`gate.py --disas` is an **index-aligned zip**, not an alignment diff. Once
|
||||
instruction counts diverge, every later row reads as different and a genuinely
|
||||
inserted or deleted block is invisible. Use `scratch/alndiff.py` (difflib
|
||||
SequenceMatcher over normalized capstone streams, branch targets normalized):
|
||||
|
||||
python scratch/build1.py <unit>.c scratch/cur.obj
|
||||
python scratch/alndiff.py <unit> <FUNC> scratch/cur.obj
|
||||
|
||||
A 48-instruction hole in `_ai_debug_render_actor` was only visible this way.
|
||||
|
||||
Ignore `.rdata` / `__real@...` annotation mismatches in that output - those are
|
||||
symbol-naming artifacts, not code differences.
|
||||
|
||||
## 3. Header edits perturb objects that never name the added types
|
||||
|
||||
**"Edit only your own object's header" is not a safe rule.**
|
||||
|
||||
`source/items/weapons.h` is included by ten other `.c` files. Adding two
|
||||
interface-state structs to it silently dropped `units.obj` from **189/189 to
|
||||
188/189**, breaking `_unit_preprocess_node_orientations` - a function that
|
||||
names none of those types and calls none of the new functions.
|
||||
|
||||
Bisecting the three added blocks:
|
||||
|
||||
| added to weapons.h | units.obj |
|
||||
| --- | --- |
|
||||
| enum only | 189 ok |
|
||||
| structs only | **188 BREAKS** |
|
||||
| protos only | 189 ok |
|
||||
| enum + structs | 189 ok |
|
||||
| structs + protos | **188 BREAKS** |
|
||||
| all three | **188 BREAKS** |
|
||||
|
||||
Adding the enum *in front of* the structs repairs it. The effect is not
|
||||
semantic - it is the C2 allocator's **definition-position** sensitivity. What
|
||||
perturbs codegen is where declarations sit, not what they mean.
|
||||
|
||||
### Rules that follow
|
||||
|
||||
1. Before touching any `.h`, run
|
||||
`grep -rl "<header filename>" source/ --include=*.c`. If anything else
|
||||
includes it, default to putting the declaration in the `.c`.
|
||||
2. Definitions private to one TU belong in that TU. The weapons fix: structs
|
||||
moved into `weapons.c`; the header kept the enum, the prototypes, and a
|
||||
forward declaration so the prototype's struct tag has file scope. `units`
|
||||
returned to 189/189 with all 50 of weapons' exact functions intact.
|
||||
3. **Never** "fix" this by relying on a coincidental ordering that happens to
|
||||
restore the victim.
|
||||
4. If a header edit is genuinely required, prove it: build **shadow header
|
||||
trees** (patched and pristine), compile every dependent unit against both,
|
||||
and compare per-function size, relocation count and normalized hash. This
|
||||
was done to drop `__declspec(align(4))` from `struct guard_state_data` in
|
||||
`actions.h` (24 includers) and it held up under independent re-check.
|
||||
|
||||
### Some cases have no local remedy
|
||||
|
||||
Adding two trailing fields to `struct _projectile_datum` in `projectiles.h` -
|
||||
fields January demonstrably uses at composite offsets 0x1FC and 0x200 - drops
|
||||
`units.obj` to 188/189. The type is public, so internalising it in the `.c`
|
||||
does not apply. About 1,152 bytes of projectile work is gated on this. That is
|
||||
an owner decision; do not trade away a complete object for it quietly.
|
||||
|
||||
## 4. Verification discipline
|
||||
|
||||
**Worker self-reports are systematically optimistic.** One wave's rolled-up
|
||||
"confirmed bytes" read 18,544 against 3,168 actually closed, because verifiers
|
||||
counted pre-existing exact functions alongside new ones.
|
||||
|
||||
The only numbers that count:
|
||||
|
||||
1. A full `ninja` build. Its semantic gate fails closed if any previously exact
|
||||
function stops matching.
|
||||
2. `python tools/campaign/board.py` for the byte and function totals.
|
||||
3. A **per-function regression sweep**: snapshot the exact set of every unit
|
||||
from `build/split` vs `build/base` before the run, and re-compare after.
|
||||
Object-level counts hide one object lost against another gained.
|
||||
|
||||
`board.py`'s per-object listing is **truncated** - an object appearing in or
|
||||
disappearing from it is not evidence of a change. Use the sweep.
|
||||
|
||||
## 5. Cross-cutting codegen facts confirmed this run
|
||||
|
||||
- **Frame size is structural.** A differing `sub esp, N` means a local's scope
|
||||
or type is wrong. It is never scheduling noise. This is what reopened
|
||||
`_generate_prime_numbers` after a prior session had declared evidence
|
||||
exhaustion on it (81.61% -> 91.15%).
|
||||
- **Local declaration order is inert** for stack-slot assignment - proven
|
||||
byte-identical across four permutations. Do not spend waves permuting
|
||||
declarations.
|
||||
- **The zero-register pin.** January frequently keeps a zero live in a register
|
||||
and spends it repeatedly (`mov [mem],reg`, `push reg`, `cmp reg,zeroreg`)
|
||||
where our build rematerialises immediates. Pinning a zero consumes a
|
||||
callee-saved register, so this surfaces *downstream* as stack-slot
|
||||
permutations and duplicated or merged blocks rather than as a local byte
|
||||
difference. It is not a compiler flag: on `_lra_allocate`, `/O1`, `/O2 /Os`
|
||||
and `/O1 /Ob2` all shrink the function to 319 bytes and `/Ox /Os` explodes it
|
||||
to 1255, while the campaign flags give the closest result at 368.
|
||||
- **Shared-header inlines must stay non-`static`.** Converting the 89
|
||||
`__inline` definitions in `real_math.h` (plus 6 elsewhere) to
|
||||
`static __inline` costs **21 objects and 119 functions**: `static` lets VC7
|
||||
dead-code the out-of-line copy and inline more aggressively, changing call
|
||||
sites. This also kills the theory that our ~20-28 surplus COMDATs per object
|
||||
come from storage class - non-static is what reproduces January's bytes, so
|
||||
the surplus-COMDAT question remains open and is a whole-tree property, not
|
||||
something an individual object's reconstruction introduced.
|
||||
|
||||
## 6. Guards against fake matching
|
||||
|
||||
A byte match bought with source Bungie would not have written is worth less
|
||||
than an honest residual. Rejected on sight: `volatile`, `register`, `#pragma`,
|
||||
barriers, compiler-flag changes, raw numeric struct offsets, type punning or
|
||||
representation casts, undefined behaviour, byte forcing, and logic that is
|
||||
nonsensical for the function's stated job and only coincidentally matches.
|
||||
|
||||
Three live examples from this run, all correctly refused:
|
||||
|
||||
- The only shape that narrowed `_ai_debug_render_actor` required
|
||||
`real_vector3d *` to `real_point3d *` casts to reach `point_from_line3d`.
|
||||
That is representation punning, so it was reverted - and re-reading the
|
||||
numbers, it only reached 24,864 of 24,976 bytes anyway. It was never a
|
||||
closure, just a 16-byte improvement on a 128-byte gap.
|
||||
- Writing an early return as `*num_primes = i` to deliberately spend a live
|
||||
zero is a coincidence generator, not a reconstruction. XDK 3911 folds it to
|
||||
identical code and it was already on a do-not-repeat list.
|
||||
- A `vehicle_update` shape that forced an increment into both arms of a clamp
|
||||
using two invented file statics measured the right size only because the
|
||||
shortfall was cancelled downstream by alignment padding. The real shape is
|
||||
the `cseries.h` `MIN` macro with the constant on the left and no local
|
||||
increment at all.
|
||||
|
||||
Inline assembly is allowed **sparingly** and **unit-locally** in small helper
|
||||
and math functions. The admitted case is `fast_ftol` (`fld` / `fistp`), because
|
||||
`/QIfist` lowers every C float-to-int conversion through a 64-bit `fistp qword`
|
||||
and a 32-bit inline `fistp` is never compiler output. Keep it `static __inline`
|
||||
in the `.c` that needs it - never in a shared header.
|
||||
|
||||
## 7. Reusable scratch tooling
|
||||
|
||||
Left in `scratch/` by this run (note that `scratch/` is per-worktree and is not
|
||||
committed, so these exist only in the worktree that produced them):
|
||||
|
||||
| file | purpose |
|
||||
| --- | --- |
|
||||
| `alndiff.py` | true alignment diff over normalized capstone streams |
|
||||
| `build1.py` | compile one unit with the real build flags to a chosen `.obj` |
|
||||
| `cs_build.py`, `cs_gate.py`, `cs_blast2.py` | shadow-header-tree blast-radius harness |
|
||||
| `pn_score.py` | score source variants by byte divergence and first-diff offset |
|
||||
| `pn_try.py` | batch-apply source variants through `gate.py` and report |
|
||||
|
||||
Use the committed `tools/fake_match_scan.py` for fake-match review; unlike the
|
||||
scratch helpers above, it is available in every checkout.
|
||||
|
||||
A caution learned twice the hard way: **Python heredocs in this environment eat
|
||||
one level of backslashes.** Build Windows path separators with `chr(92)` rather
|
||||
than writing them literally, or you will silently emit a single-backslash
|
||||
`__FILE__` string where the source needs a doubled one and break relocation
|
||||
identity against the target's string literal.
|
||||
@@ -1,355 +0,0 @@
|
||||
# Common constants and representation reference
|
||||
|
||||
Verified against canonical on 2026-09-08. Start here before guessing literals.
|
||||
|
||||
This is a lookup guide, not a new constants owner. Most rows record high-use
|
||||
names that already have canonical owners; the supplied-source crosswalk is
|
||||
explicitly separate. Future reconstructions should include the
|
||||
owning header and use the existing symbol or macro; they should not duplicate
|
||||
these declarations in a translation unit merely to obtain a desired code
|
||||
shape.
|
||||
|
||||
`Confirmed` below means the value and spelling are present in the named
|
||||
canonical owner. Float bits show the rounded binary32 representation; tag
|
||||
immediates use the pinned MSVC convention. January corroboration is called out
|
||||
explicitly below. A recognizable bit pattern is a lookup clue, not proof of
|
||||
which source expression produced it. `Context-specific` means a value belongs
|
||||
to the stated enum, storage type, or algorithm, not an unrelated global owner.
|
||||
|
||||
## Core values and representations (confirmed)
|
||||
|
||||
| Purpose | Canonical symbol / type | Value or representation | Owning source | Important boundary |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Boolean true/false | `TRUE`, `FALSE` | `1`, `0` | [source/cseries/cseries.h](../source/cseries/cseries.h) | Use these for the project's one-byte `boolean` APIs. A `boolean` i386 return may define only `AL`; a `void` return promises no value. Do not require unrelated upper `EAX` bits. |
|
||||
| Invalid signed index/handle | `NONE` | `-1` (`0xFFFFFFFF` as a 32-bit `long`) | [source/cseries/cseries.h](../source/cseries/cseries.h) | This is not `NULL`. Confirm the destination width: a byte or word sentinel has the narrowed all-ones representation, and some APIs use zero as a distinct valid or invalid value. |
|
||||
| Simulation rate | `TICKS_PER_SECOND`, `ACTUAL_TICKS_PER_SECOND` | `30`, `30` | [source/cseries/cseries.h](../source/cseries/cseries.h) | Express seconds-to-ticks as `seconds * TICKS_PER_SECOND`; express per-tick scale as `1.0f / TICKS_PER_SECOND`. Do not invent a `SECONDS_PER_TICK` owner. The latter folds to float bits `0x3D088889`. |
|
||||
| Wall-clock unit | `MILLISECONDS_PER_SECOND` | `1000` | [source/cseries/cseries.h](../source/cseries/cseries.h) | Do not mix millisecond tag fields with 30 Hz game ticks. Existing code explicitly converts when needed. |
|
||||
| Display cadence | `VBLANKS_PER_SECOND` | `60` | [source/cseries/cseries.h](../source/cseries/cseries.h) | Vblanks are not simulation ticks even though both are integer rates. |
|
||||
| Integer widths | `LONG_BITS`, `SHORT_BITS`, `CHAR_BITS` | `32`, `16`, `8` | [source/cseries/cseries.h](../source/cseries/cseries.h) | These describe the January/Win32 ABI. Preserve signedness as well as width. |
|
||||
| Integer extrema | `LONG_MAX`, `LONG_MIN`, `UNSIGNED_LONG_MAX`, `SHORT_MAX`, `SHORT_MIN`, `UNSIGNED_SHORT_MAX` | `2147483647`, `-2147483648`, `0xFFFFFFFF`, `32767`, `-32768`, `0xFFFF` | [source/cseries/cseries.h](../source/cseries/cseries.h) | Prefer the named bound. `UNSIGNED_LONG_MAX` is also the canonical all-object mask, but that does not make it a universal sentinel. |
|
||||
| Scalar real | `real` | `typedef float real` (4-byte IEEE-754 binary32 in target ABI) | [source/cseries/cseries.h](../source/cseries/cseries.h) | Use `f` suffixes for ordinary `real` constants. Use `double` only where the genuine API or default vararg promotion requires it. |
|
||||
| Engine boolean | `boolean` | `typedef byte boolean`; `byte` is `unsigned char` | [source/cseries/cseries.h](../source/cseries/cseries.h) | It is one byte, not C/C++ `bool` and not a four-byte `long`. This affects fields, parameters, stack snapshots, and return checks. |
|
||||
| Tag word | `tag` | `typedef unsigned long tag` (32 bits in target ABI) | [source/cseries/cseries.h](../source/cseries/cseries.h) | Preserve the four-character group token and the unsigned 32-bit type. |
|
||||
| Coordinate axes | `_x`, `_y`, `_z` | `0`, `1`, `2` | [source/cseries/cseries.h](../source/cseries/cseries.h) | Use these only as component/projection indices. They are not vector values or bit masks. |
|
||||
| Geometric tolerance | `_real_epsilon` | `0.0001f`, binary32 bits `0x38D1B717` | [source/math/real_math.h](../source/math/real_math.h) | This is not a universal replacement for exact-zero tests. January functions use both epsilon and exact `0.0f`; preserve the observed predicate and NaN behavior. |
|
||||
| Pi | `_pi` | `(real)M_PI`, binary32 bits `0x40490FDB` | [source/math/real_math.h](../source/math/real_math.h) | Use the project cast rather than a hand-rounded decimal when the source works in `real`. |
|
||||
| Angle conversion | `DEGREES_TO_RADIANS`, `RADIANS_TO_DEGREES` | `((real)angle) * _pi / 180.f` or `((real)angle) * 180.f / _pi` | [source/math/real_math.h](../source/math/real_math.h) | Angles stored in tags are not uniformly degrees or radians. First authenticate the field's unit; then use the owner macro. Expression order can affect exact float bytes. |
|
||||
| Finite real envelope | `REAL_MIN`, `REAL_MAX` | `-3.4028235e38f`, `3.4028235e38f` | [source/math/real_math.h](../source/math/real_math.h) | `REAL_MIN` here is the most-negative finite bound, not the C-library meaning “smallest positive normal.” |
|
||||
|
||||
January examples that corroborate the float rows are the
|
||||
`__real@38d1b717`, `__real@41f00000`, and `__real@3d088889` relocations in
|
||||
`build/split/source/objects/damage.obj`. They represent `_real_epsilon`,
|
||||
`(real)TICKS_PER_SECOND`, and `1.0f / TICKS_PER_SECOND`; they do not justify
|
||||
replacing the source-level owners with hexadecimal literals.
|
||||
|
||||
## Canonical macros whose semantics matter
|
||||
|
||||
| Macro | Definition owner | Correct use | Pitfall |
|
||||
| --- | --- | --- | --- |
|
||||
| `MIN(a,b)`, `MAX(a,b)` | [source/cseries/cseries.h](../source/cseries/cseries.h) | Ordinary project min/max spelling when January establishes the same comparison and argument order. | Each expression can be evaluated more than once. Argument order controls signed-zero and NaN outcomes: do not normalize or swap operands merely because finite results look equivalent. |
|
||||
| `FLOOR`, `CEILING`, `PIN` | [source/cseries/cseries.h](../source/cseries/cseries.h) | Named lower/upper/clamp operations. | `PIN` is a macro composition, not an IEEE `fminf`/`fmaxf` substitute. It may evaluate the value repeatedly and lets a NaN value pass through under its current ordering. |
|
||||
| `FLAG(bit)` | [source/cseries/cseries.h](../source/cseries/cseries.h) | Convert an enum *bit index* to a mask. | Most `_..._bit` enum members are indices, not masks. Do not apply `FLAG` again to an existing `_..._mask_*` value. Preserve the owning integer width, especially near bit 31. |
|
||||
| `TEST_FLAG`, `SET_FLAG` | [source/cseries/cseries.h](../source/cseries/cseries.h) | Test or mutate a named bit in the authenticated field. | Do not replace an enum bit with a raw hex mask. Avoid side-effecting lvalues/expressions because these are macros. |
|
||||
| `VALID_FLAGS(flags,bits)` | [source/cseries/cseries.h](../source/cseries/cseries.h) | Validate that no bit at or above the declared count is set. | `bits` is a count, not a mask; signedness and shift width matter. |
|
||||
| `BIT_VECTOR_SIZE_IN_LONGS`, `BIT_VECTOR_TEST_FLAG`, `BIT_VECTOR_SET_FLAG` | [source/cseries/cseries.h](../source/cseries/cseries.h) | Long-word-packed bit vectors, 32 flags per `long`. | The macros index a `long` array. Do not silently cast an original `byte *` API to this representation. A byte-buffer use needs independent owner/caller evidence, as documented for the collision BSP boundary in [docs/object_matching_logs/collision_bsp_obj_sphere_cluster_20260904.md](object_matching_logs/collision_bsp_obj_sphere_cluster_20260904.md). |
|
||||
| `NUMBEROF(array)` | [source/cseries/cseries.h](../source/cseries/cseries.h) | Compile-time count of an actual array in the same scope. | On a pointer it returns a pointer-size ratio, not the pointee count. |
|
||||
| `VALID_INDEX(index,count)` | [source/cseries/cseries.h](../source/cseries/cseries.h) | Signed lower-bound and upper-bound check. | Preserve the signed type. Replacing it with an unsigned comparison can alter code shape and invalid-negative behavior. |
|
||||
| `DATUM_INDEX_NEW`, `DATUM_INDEX_TO_ABSOLUTE_INDEX`, `DATUM_INDEX_TO_IDENTIFIER` | [source/cseries/cseries.h](../source/cseries/cseries.h) | Construct or split the 16-bit absolute index / 16-bit identifier handle representation. | A datum handle is not a plain array index. Mask before indexing; do not discard the identifier except at a proven boundary. |
|
||||
| `TAG_BLOCK_GET_ELEMENT` | [source/tag_files/tag_groups.h](../source/tag_files/tag_groups.h) | Typed access through `tag_block_get_element_with_size(..., sizeof(type))`. | The type and element size are part of the runtime contract. Avoid a raw `address + index*stride` replacement. |
|
||||
|
||||
## Tag strings and common group IDs (confirmed)
|
||||
|
||||
`TAG_STRING_LENGTH` is **31** ([source/tag_files/tag_files.h](../source/tag_files/tag_files.h)). A
|
||||
canonical fixed tag string buffer that includes its terminator is therefore
|
||||
usually `char name[TAG_STRING_LENGTH + 1]`, or 32 bytes. The constant is a
|
||||
payload limit, not permission to omit the final NUL.
|
||||
|
||||
MSVC packs the following four-character constants into the shown immediate
|
||||
value. Always write the named owner; the hex form is provided only to read
|
||||
disassembly and relocations. On little-endian x86 the bytes in memory appear
|
||||
least-significant byte first.
|
||||
|
||||
| Domain | Symbol | Source token / i386 immediate | Owner |
|
||||
| --- | --- | --- | --- |
|
||||
| Game globals | `GAME_GLOBALS_TAG` | `'matg'` / `0x6D617467` | [source/game/game_globals.h](../source/game/game_globals.h) |
|
||||
| Scenario | `SCENARIO_TAG` | `'scnr'` / `0x73636E72` | [source/scenario/scenario_definitions.h](../source/scenario/scenario_definitions.h) |
|
||||
| Structure BSP | `STRUCTURE_BSP_TAG` | `'sbsp'` / `0x73627370` | [source/structures/structure_bsp_definitions.h](../source/structures/structure_bsp_definitions.h) |
|
||||
| Base object definition | `OBJECT_DEFINITION_TAG` | `'obje'` / `0x6F626A65` | [source/objects/object_definitions.h](../source/objects/object_definitions.h) |
|
||||
| Damage effect | `DAMAGE_EFFECT_DEFINITION_TAG` | `'jpt!'` / `0x6A707421` | [source/objects/damage_effect_definitions.h](../source/objects/damage_effect_definitions.h) |
|
||||
| Bitmap | `BITMAP_GROUP_TAG` | `'bitm'` / `0x6269746D` | [source/bitmaps/bitmap_group.h](../source/bitmaps/bitmap_group.h) |
|
||||
| Sound | `SOUND_DEFINITION_TAG` | `'snd!'` / `0x736E6421` | [source/sound/sound_definitions.h](../source/sound/sound_definitions.h) |
|
||||
|
||||
Four-character C constants are implementation-defined outside this compiler
|
||||
context. Do not byte-swap them manually or replace a typed getter such as
|
||||
`object_definition_get` with a raw `tag_get` call only to expose the numeric
|
||||
immediate.
|
||||
|
||||
## Common engine enums and limits (confirmed, domain-specific)
|
||||
|
||||
| Domain | Symbol(s) | Value | Owner and boundary |
|
||||
| --- | --- | --- | --- |
|
||||
| Local rendering/input players | `MAXIMUM_LOCAL_PLAYERS` | `4` | [source/game/players.h](../source/game/players.h). This is not the network/player-datum capacity. |
|
||||
| Network join token | `NETWORK_JOIN_GAME_TOKEN_SIZE` | `16` | [source/networking/network_messages.h](../source/networking/network_messages.h). Protocol byte count, corroborated by the supplied source and January's generator/callers; restored in the canonical protocol owner, not a claim about the absent original header. |
|
||||
| Network header direction | `_byte_order_host`, `_byte_order_network` | `0`, `1` | [source/bungie_net/common/message_header.h](../source/bungie_net/common/message_header.h). January inbound reads pass 0; outbound connection/key/rejection writes pass 1. The former inferred host/network labels were reversed; the corrected names preserve every caller's immediate and emitted code. |
|
||||
| Connection creation flags | `_connection_create_server_bit`, `_connection_create_clientside_client_bit`, `_connection_create_serverside_client_bit` | Bit indices `0`, `1`, `2`; masks `1`, `2`, `4` | [source/networking/network_connection.h](../source/networking/network_connection.h). Use `FLAG` at creation calls; these are not the separate closed/stale state bits. |
|
||||
| Network game ports | `NETWORK_GAME_SERVER_PORT`, `NETWORK_GAME_CLIENT_PORT` | `0x141E`, `0x141F` / `5150`, `5151` | [source/networking/network_game_protocol.h](../source/networking/network_game_protocol.h). Shared only by actual protocol consumers; values are not transport-type ordinals. |
|
||||
| Server rejection reasons | `_rejection_code_version_too_old` through `_rejection_code_blacklisted_machine`; `NUMBER_OF_SERVER_REJECTION_CODES` | Reasons `0..6`, count `7`; game full `4` | [source/networking/network_game_protocol.h](../source/networking/network_game_protocol.h). Serialized rejection field is a `word`; count is an exclusive bound, not a valid reason. |
|
||||
| Connection timeout disabled | `_connection_dont_timeout` | `0` | [source/networking/network_connection.h](../source/networking/network_connection.h). The idle API tests a nonzero timeout before enforcing it. This literal is not the separate `global_connection_dont_timeout` debug boolean. Name from supplied source, value from January, header placement reconstructed. |
|
||||
| Public-endpoint datagram capacity | `DATAGRAM_MAXIMUM_SIZE` | `400` / `0x190` bytes | [source/networking/network_connection.h](../source/networking/network_connection.h). Shared connection/provider limit, distinct from the reliable-message receive capacity below. `network_connection_read` takes a `word *` size; a DWORD stack-slot initialization does not make this a 32-bit API. |
|
||||
| IPv4 loopback address | `IPV4_LOOPBACK_ADDRESS` | `0x7F000001` | [source/bungie_net/network/transport_address_constants.h](../source/bungie_net/network/transport_address_constants.h). Source-attested spelling and January compare immediate. Use in the transport address's host-order IPv4 field, not as four already serialized network bytes. This narrow shared header is included by the actual client/server consumers. |
|
||||
| Client/server receive buffer | `MAXIMUM_NETWORK_MESSAGE_SIZE` | `0x800` / `2048` bytes | Local manager enums in [server](../source/networking/network_server_manager.c) and [client](../source/networking/network_client_manager.c). January proves the buffer and word-sized capacity reset. This is not `MAXIMUM_MESSAGE_SIZE=0xFFF` in the separate Bungie-net message header. A word-aligned array preserves the receiving handler's genuine word-pointer contract. |
|
||||
| Difficulty | `_game_difficulty_level_easy`, `_game_difficulty_level_normal`, `_game_difficulty_level_hard`, `_game_difficulty_level_impossible` | `0`, `1`, `2`, `3` | [source/game/game.h](../source/game/game.h). Use the enum; a raw ordinal is ambiguous at a call site. |
|
||||
| Campaign team | `_game_team_default`, `_game_team_player`, `_game_team_human`, `_game_team_covenant`, `_game_team_flood`, `_game_team_sentinel` | `0` through `5` | [source/game/game.h](../source/game/game.h). Multiplayer `_team_red=0`, `_team_blue=1` intentionally overlaps numerically; the field/API determines the namespace. |
|
||||
| Object types | `_object_type_biped` through `_object_type_sound_scenery` | `0` through `11`; `NUMBER_OF_OBJECT_TYPES=12` | [source/objects/object_types.h](../source/objects/object_types.h). Values are ordinals used by object headers and switch statements. |
|
||||
| Object masks | `_object_mask_unit`, `_object_mask_item`, `_object_mask_device`, `_object_mask_all` | `0x3`, `0x1C`, `0x380`, `0xFFFFFFFF` | [source/objects/object_types.h](../source/objects/object_types.h). These are already masks; test them against an object type with the established `TEST_FLAG(mask, type)` convention. |
|
||||
| Object capacity | `MAXIMUM_OBJECTS_PER_MAP` | `2048` | [source/objects/objects.h](../source/objects/objects.h). Capacity is not the current datum count. |
|
||||
| Rendered-object capacity | `MAXIMUM_RENDERED_OBJECTS` | `256` | [source/objects/objects.h](../source/objects/objects.h). Do not use it to size the master object datum array. |
|
||||
| UI deletion input-inhibit mask | `WIDGET_DELETED_PLAYER_CONTROL_INHIBIT_FLAGS` | `0x0FFF` | TU-local owner in [source/interface/ui_widget.c](../source/interface/ui_widget.c). Passed as a `word` to `player_control_inhibit_buttons` when a root widget with a non-`NONE` local-player index is deleted. It fences the evidenced low twelve discrete action buttons until each held button is released; it does not cover analog movement/look, and it is not `UNSIGNED_SHORT_MAX`, a universal all-buttons mask, or a bit index for `FLAG`. |
|
||||
| Markers/regions/attachments | `MAXIMUM_MARKERS_PER_OBJECT`, `MAXIMUM_REGIONS_PER_OBJECT`, `MAXIMUM_NUMBER_OF_ATTACHMENTS_PER_OBJECT` | `64`, `8`, `8` | [source/objects/objects.h](../source/objects/objects.h) and [source/objects/object_definitions.h](../source/objects/object_definitions.h). These belong to different arrays despite sharing an object definition. |
|
||||
| Damage material modifier capacity | `MAXIMUM_NUMBER_OF_MATERIAL_TYPES` | `40` | [source/game/game_globals.h](../source/game/game_globals.h); used by `damage_definition.material_modifiers` at [source/objects/damage_effect_definitions.h](../source/objects/damage_effect_definitions.h). It is storage capacity, not the current named-material count. |
|
||||
|
||||
## Xbox shader encodings (confirmed SDK owners, context-specific)
|
||||
|
||||
The existing [Xbox D3D8 types header](../xbox/include/D3D8Types.h) owns the
|
||||
register-combiner macros and enums. Prefer them to packed hexadecimal shader
|
||||
words; this documents the actual inputs and outputs without creating new
|
||||
engine constants. They are hardware encodings, not Bungie identifier recovery.
|
||||
|
||||
| Encoding | Existing owner / interpretation | Example |
|
||||
| --- | --- | --- |
|
||||
| Four combiner inputs | `PS_COMBINERINPUTS(a,b,c,d)` packs four input bytes | `PS_COMBINERINPUTS(PS_REGISTER_T0, PS_REGISTER_T0, PS_REGISTER_ZERO, PS_REGISTER_ZERO)` is `0x08080000`. |
|
||||
| Input register/mapping/channel | `PS_REGISTER_*`, `PS_INPUTMAPPING_*`, `PS_CHANNEL_*` | `PS_REGISTER_V0 \| PS_INPUTMAPPING_UNSIGNED_INVERT` is `0x24`; `PS_REGISTER_V1 \| PS_CHANNEL_ALPHA` is `0x15`. These are already encoded masks, not bit indices for `FLAG`. |
|
||||
| Constant one input | `PS_REGISTER_ONE` | `0x20`, zero register with unsigned-invert mapping; not a literal register number 32. |
|
||||
| Combiner destinations | `PS_COMBINEROUTPUTS(ab,cd,mux_sum,flags)` | R0/discard/discard/identity is `0xC0`; R1/discard/discard/identity is `0xD0`. |
|
||||
| Stage count | `PS_COMBINERCOUNT(count,flags)` | Counts 1 and 3 with zero flags encode as 1 and 3. Flags zero select the SDK defaults; count is not a bit index. |
|
||||
| Texture addressing modes | `PS_TEXTUREMODES(t0,t1,t2,t3)` with `PS_TEXTUREMODES_*` | PROJECT2D/NONE/NONE/NONE encodes as 1. |
|
||||
|
||||
The Widgets reconciliation replaces these packed words using the existing
|
||||
macros; all generated code and non-debug sections remain unchanged. Do not
|
||||
assign a fixed-function `D3DVSDE_*` semantic name to an arbitrary custom vertex
|
||||
shader register just because its number agrees: Widgets sends color through
|
||||
register 9 and texture coordinates through register 4. The custom shader's
|
||||
input contract, not the fixed-function spelling, determines their meaning.
|
||||
|
||||
## Damage flags relevant to the current caller/helper packet
|
||||
|
||||
These are confirmed but context-specific. The enum values are **bit indices**;
|
||||
use `TEST_FLAG`/`SET_FLAG` rather than the numeric masks shown for audit
|
||||
convenience.
|
||||
|
||||
| Storage | Symbol | Bit / mask | Owner |
|
||||
| --- | --- | --- | --- |
|
||||
| `being_damaged_flags` | `_object_being_damaged_body_depleted_bit` | `0` / `0x01` | [source/objects/damage.h](../source/objects/damage.h) |
|
||||
| `being_damaged_flags` | `_object_being_damaged_shield_depleted_bit` | `3` / `0x08` | [source/objects/damage.h](../source/objects/damage.h) |
|
||||
| `being_damaged_flags` | `_object_being_damaged_by_friendly_bit` | `4` / `0x10` | [source/objects/damage.h](../source/objects/damage.h) |
|
||||
| `being_damaged_flags` | `_object_being_damaged_multiplied_by_difficulty_bit` | `5` / `0x20` | [source/objects/damage.h](../source/objects/damage.h) |
|
||||
| `damage_data.flags` | `_damage_no_statistics_bit` | `7` / `0x80` | [source/objects/damage.h](../source/objects/damage.h) |
|
||||
| `object.damage_flags` | `_object_passed_shield_damage_threshold_bit` | `1` / `0x0002` | [source/objects/objects.h](../source/objects/objects.h) |
|
||||
| `object.damage_flags` | `_object_shield_depleted_bit` | `3` / `0x0008` | [source/objects/objects.h](../source/objects/objects.h) |
|
||||
| `object.damage_flags` | `_object_shield_over_charging_bit` | `4` / `0x0010` | [source/objects/objects.h](../source/objects/objects.h) |
|
||||
| `object.damage_flags` | `_object_cannot_take_damage_bit` | `11` / `0x0800` | [source/objects/objects.h](../source/objects/objects.h) |
|
||||
|
||||
Do not merge the two “shield depleted” names: one is an event/result bit in a
|
||||
32-bit accumulator and the other is persistent object state in a 16-bit
|
||||
field. Their current numeric bit happens to be the same.
|
||||
|
||||
January-specific category, side-effect, material-response, and private-helper
|
||||
values should remain in the owning Damage enum unless a genuine shared owner
|
||||
is found. A comparison against `1`, `2`, or `3` in disassembly is not enough
|
||||
to infer which enum namespace it belongs to. Likewise, the Damage aftermath
|
||||
upward bias and similar algorithm coefficients are not general math
|
||||
constants; retain a semantic local expression and document its function-level
|
||||
provenance instead of exporting a global name.
|
||||
|
||||
## Assertions and object-access macros
|
||||
|
||||
See [the shared assertion API and Units example](assertions.md). Assertions test
|
||||
an invariant that must be true; a diagnostic error condition usually needs
|
||||
negating. `_object_connected_to_map_bit` is bit 11 in `object.flags`, whereas
|
||||
`_object_header_connected_to_map_bit` is bit 5 in a separate header flags byte.
|
||||
Do not substitute one for the other.
|
||||
|
||||
Use typed accessors such as `unit_get`, `weapon_get`, `object_definition_get`,
|
||||
`bitmap_group_get`, and `sound_definition_get` from their existing subsystem
|
||||
headers. Keep raw `tag_get` and object-access casts encapsulated there rather
|
||||
than repeating casts at each call site.
|
||||
|
||||
## Supplied-source crosswalk (evidence, not yet canonical declarations)
|
||||
|
||||
The user supplied three CE source files on 2026-09-06. Their hashes, local
|
||||
locations, target fingerprints, and integration caveats are recorded in the
|
||||
[source reconstruction map](user_source_reconstruction_map_20260906.md).
|
||||
The following names occur there; do not assume they are already available
|
||||
from canonical headers or export TU-private coefficients globally.
|
||||
|
||||
| Supplied name / expression | Value | Canonical correspondence and scope |
|
||||
| --- | --- | --- |
|
||||
| `RANDOM_A` | `1664525L` / `0x0019660D` | Literal in [source/math/random_math.c](../source/math/random_math.c); LCG multiplier, not a general math constant. |
|
||||
| `RANDOM_C` | `1013904223L` / `0x3C6EF35F` | Same owner; LCG increment. Seed arithmetic is unsigned 32-bit modulo arithmetic. |
|
||||
| `RANDOM(seed)` | Update seed, then take its upper 16 bits | Source macro uses a 16-bit right shift; do not substitute low bits or mutate the seed twice. |
|
||||
| `REAL_RANDOM(seed)` | `(1.f / (real)0xffff) * RANDOM(seed)` | Divisor is `65535`, not `65536`; the source real result can reach both 0 and 1. Integer range scaling instead uses a right shift by 16 and is upper-exclusive for its valid range. Preserve expression order and promotions. |
|
||||
| `RANDOM_DIRECTION_TABLE_GEOSPHERE_SEGMENT_COUNT` | `16` | RandomMath's geosphere construction argument, not a player capacity or direction-table length. |
|
||||
| `COUNTDOWN_TIMER_CANNOT_ACCLERATE_AMOUNT` | `MILLISECONDS_PER_SECOND - 1` = `999` | Source spelling includes `ACCLERATE`; canonical server calls it `NETWORK_GAME_MINIMUM_COUNTDOWN_TIME`. |
|
||||
| `CLIENT_COUNTDOWN_TIMER_MODIFICATION_AMOUNT` | `5 * MILLISECONDS_PER_SECOND` = `5000` | Canonical server `NETWORK_GAME_COUNTDOWN_ADJUSTMENT`. |
|
||||
| `LAN_INITIAL_SERVER_GAME_COUNTDOWN` | `31 * MILLISECONDS_PER_SECOND - 1` = `30999` | Canonical server `NETWORK_GAME_COUNTDOWN_TIME`. |
|
||||
| `LOCAL_INITIAL_SERVER_GAME_COUNTDOWN` | `11 * MILLISECONDS_PER_SECOND - 1` = `10999` | Canonical server `NETWORK_GAME_SPLITSCREEN_COUNTDOWN_TIME`. |
|
||||
| `MAXIMUM_SERVER_GAME_COUNTDOWN` | `31 * MILLISECONDS_PER_SECOND - 1` = `30999` | Separate semantic role from the LAN initial time, despite equal values. |
|
||||
| `NETWORK_GAME_CLIENT_CONNECTION_PROCESS_TIMEOUT_MILLISECONDS` | Debug `120000`; release `15000` | Supplied client enum selects `120` or `15` times `MILLISECONDS_PER_SECOND` under `DEBUG`; do not use one build's timeout in the other. |
|
||||
| `NETWORK_GAME_CLIENT_GAME_SEARCH_INTERVAL_MILLISECONDS` | `2000` | Supplied client search cadence, `2 * MILLISECONDS_PER_SECOND`. |
|
||||
| `NETWORK_GAME_CLIENT_GAME_ADVERTISED_GAME_TIMEOUT` | `6000` | Supplied client: twice the search interval plus `2 * MILLISECONDS_PER_SECOND`; not the connection timeout. |
|
||||
| `NETWORK_GAME_CLIENT_GAME_PING_INTERVAL_MILLISECONDS` | `1000` | Supplied client ping cadence, `1 * MILLISECONDS_PER_SECOND`. |
|
||||
| `NETWORK_GAME_CLIENT_INITIAL_PACKET_SEQUENCE_NUMBER` | `1` | Supplied client protocol sequence origin; not a universal first array index. |
|
||||
|
||||
Countdown correspondences are in
|
||||
[source/networking/network_server_manager.c](../source/networking/network_server_manager.c).
|
||||
The supplied server's client-machine flag indices are connected `0`,
|
||||
validated `1`, level-loaded `2`, and precached `3`. Canonical currently uses
|
||||
joined/loaded names for indices 1/2; numeric agreement alone does not authorize
|
||||
a global semantic rename. These flags are not object-datum flags.
|
||||
|
||||
The supplied RandomMath also references `_full_circle`, `_half_circle`, and
|
||||
`_quarter_circle`, but their defining header was not supplied and they are not
|
||||
present in the current canonical math headers. Do not invent a declaration
|
||||
or infer exact expression ordering solely from those names.
|
||||
|
||||
The supplied client names its two flag indices
|
||||
`_network_game_client_connected_to_server_bit = 0` and
|
||||
`_network_game_client_sent_join_request_to_server_bit = 1`. Canonical uses
|
||||
shorter inferred names and literal timing values; restore names only with
|
||||
ordinary strict-object and consumer checks, not by unreviewed bulk replacement.
|
||||
|
||||
## AI profile meter layout
|
||||
|
||||
January's shared AI profiling state is declared in
|
||||
`source/ai/ai_profile.h`. Include that owner when incrementing a meter; do not
|
||||
declare an opaque `extern byte ai_profile[]`, a partial local structure, or a
|
||||
consumer-specific view of the same global.
|
||||
|
||||
- `ai_profile.meters` begins at offset `0x0C`.
|
||||
- There are 28 meter records, each `0x88` bytes.
|
||||
- `accumulator` is at record offset `0`; `current_value` is at offset `2`.
|
||||
- A meter accumulator is therefore at `0x0C + index * 0x88`.
|
||||
|
||||
Frequently used indices and accumulator offsets:
|
||||
|
||||
| meter enum | index | offset |
|
||||
| --- | ---: | ---: |
|
||||
| `_ai_meter_encounters_updated` | 1 | `0x094` |
|
||||
| `_ai_meter_actors_updated` | 3 | `0x1A4` |
|
||||
| `_ai_meter_actors_active` | 4 | `0x22C` |
|
||||
| `_ai_meter_units_updated` | 6 | `0x33C` |
|
||||
| `_ai_meter_units_active` | 7 | `0x3C4` |
|
||||
| `_ai_meter_dead_props_acknowledged` | 9 | `0x4D4` |
|
||||
| `_ai_meter_dead_props_orphaned` | 10 | `0x55C` |
|
||||
| `_ai_meter_dead_props_unacknowledged` | 11 | `0x5E4` |
|
||||
| `_ai_meter_enemy_props_acknowledged` | 12 | `0x66C` |
|
||||
| `_ai_meter_enemy_props_orphaned` | 13 | `0x6F4` |
|
||||
| `_ai_meter_enemy_props_unacknowledged` | 14 | `0x77C` |
|
||||
| `_ai_meter_friendly_props_acknowledged` | 15 | `0x804` |
|
||||
| `_ai_meter_friendly_props_orphaned` | 16 | `0x88C` |
|
||||
| `_ai_meter_friendly_props_unacknowledged` | 17 | `0x914` |
|
||||
| `_ai_meter_collisions` | 21 | `0xB34` |
|
||||
| `_ai_meter_line_of_sight` | 22 | `0xBBC` |
|
||||
| `_ai_meter_line_of_fire` | 23 | `0xC44` |
|
||||
| `_ai_meter_action_change` | 26 | `0xDDC` |
|
||||
|
||||
The leading booleans are independently exposed through the Halo Script
|
||||
global table, which authenticates their names and offsets: `disabled` at
|
||||
`0x00`, `move_actors_randomly` at `0x01`, `show` through
|
||||
`show_sound_distance` at `0x04` through `0x0B`. The complete global is
|
||||
`0xEEC` bytes.
|
||||
|
||||
## Reconstruction checklist
|
||||
|
||||
1. Search for an existing owner before adding a constant, enum, macro, or
|
||||
typedef. Include that owner instead of redeclaring it locally when header
|
||||
placement is safe.
|
||||
2. Establish the storage type and namespace before interpreting `-1`, `0`, or
|
||||
a bit number. `NONE`, `NULL`, a tag index, and a byte terminator are not
|
||||
interchangeable merely because some bytes match.
|
||||
3. Compare exact float bytes and x87 predicates before replacing a literal
|
||||
with `_real_epsilon`, `MIN`, `MAX`, or `PIN`. Finite agreement does not
|
||||
prove NaN, infinity, tangent, or signed-zero agreement.
|
||||
4. Treat enum `_..._bit` members as bit positions and `_..._mask...` members
|
||||
as masks. Keep the owning field width; do not widen a byte/word flag field
|
||||
to `long *` for macro convenience.
|
||||
5. Treat every maximum as a capacity for its named owner, not a current count
|
||||
or a substitute capacity for a nearby array.
|
||||
6. Preserve public type widths at ABI boundaries. In particular, `real` is
|
||||
float and `boolean` is byte even when i386 register or stack mechanics make
|
||||
a mismatched declaration appear to work.
|
||||
|
||||
## Leaf Map construction constants (context-specific)
|
||||
|
||||
These values are authenticated by January's Leaf Map strings, data, control
|
||||
flow, and the reconciled private caller graph. They belong to
|
||||
`source/structures/leaf_map.c`; they are not general geometry constants.
|
||||
|
||||
| Role | Source spelling / value | Boundary |
|
||||
| --- | --- | --- |
|
||||
| BSP traversal stack capacity | `MAXIMUM_NODE_STACK_COUNT = 256` | Assertion text names the constant and aggregate field. Stack entries are signed node designators whose sign bit records the child side. |
|
||||
| Initial face polygon capacity | `MAXIMUM_LEAF_FACE_VERTICES = 64` | Bounds the local clipped polygon and the correctly owned Geometry clip call. |
|
||||
| Portal intersection capacity | `MAXIMUM_PORTAL_VERTICES = 64` | Bounds the temporary intersection polygon; it is not a generic tag-block capacity. |
|
||||
| Initial projected world square | coordinates `+/-1536.f` | The four-point polygon is clipped by every ancestor BSP plane; do not export 1536 as a world-wide coordinate bound. |
|
||||
| Leaf-face clip epsilon | `0.000244140625f` (`1/4096`) | Algorithm-specific clip tolerance, distinct from `_real_epsilon`. |
|
||||
| Portal intersection epsilon | `0.00048828125f` (`1/2048`) | Algorithm-specific intersection tolerance. |
|
||||
| Portal closure thresholds | area `< 0.0025f` or `sqrt(area)/perimeter < 0.01f` | Preserve expression order and the perimeter call; these are not generic degenerate-polygon rules. |
|
||||
|
||||
See [the Leaf Map reconciliation ledger](object_matching_logs/leaf_map_obj_private_graph_reconciliation_20260909.md)
|
||||
for symbol provenance, strict-credit boundaries, and the remaining data/BSS
|
||||
gap.
|
||||
|
||||
## Rasterizer shared-state lookup
|
||||
|
||||
Use `source/rasterizer/rasterizer_frame_statistics.h` for the complete January
|
||||
**0x170-byte** frame-statistics record and its external declaration. Do not
|
||||
introduce another consumer-specific prefix. Dynamic buffer counts are not
|
||||
maximum capacities; model skinning/lighting accumulators count uploaded
|
||||
constant bytes, not objects. See the
|
||||
[shared counter owner ledger](object_matching_logs/rasterizer_frame_statistics_obj_shared_counter_owner_20260906.md)
|
||||
for the current writer-backed fields and intentionally unreviewed interiors.
|
||||
|
||||
Use `source/rasterizer/rasterizer_debug_options.h` for the genuine January
|
||||
debug-options record; do not add another TU-local prefix. The size is **0x8C**
|
||||
(not later HCEA's 0x90). Active Camouflage flags are at 0x41/0x42; January
|
||||
`zbias` at 0x54 is `long`, not `real`; `pad3_scale` is at 0x6C and the six
|
||||
debug reals start at 0x70. The pixel-counter active/enabled pair is 0x88/0x89.
|
||||
Unknown bytes must not inherit later-build names merely by offset.
|
||||
|
||||
The complete 0xF0 Xbox `pixel_shader_definition` is in
|
||||
`source/rasterizer/xbox/rasterizer_xbox_pixel_shader.h`. Use this associated
|
||||
header when a complete type is needed; the broad Xbox header retains its
|
||||
forward declaration to avoid colliding with legacy local definitions.
|
||||
See the [shared-owner/cache admission](object_matching_logs/rasterizer_xbox_active_camouflage_obj_shared_owner_cache_20260906.md)
|
||||
for provenance, the typed initializer and pinned-compiler layout tests.
|
||||
|
||||
### PlayerProfile and S3TC constants
|
||||
|
||||
January; 2026-09-07 owner reconciliation:
|
||||
|
||||
- `source/saved games/player_profile.h` owns the 48-byte profile: name is
|
||||
12 wchar_t at +0, color short at +24, flags word at +26, ten byte map flags
|
||||
at +28, last level short at +38 and eight-byte controller settings at +40.
|
||||
These are not the larger later-PC/PDB profile layout.
|
||||
- `SAVED_GAME_FILE_BLOCK_SIZE` is 512 in saved_game_files.h. PlayerProfile's
|
||||
typed file block has 48 profile bytes, a 20-byte XDK signature and 444 bytes
|
||||
of zeroed padding. Do not serialize uninitialized padding for matching.
|
||||
- `S3TC_BLOCK_PIXELS` is 16 (4 by 4); single-pixel coordinates are 0..3.
|
||||
RGB565 is blue/green/red 5/6/5 in the project's byte-channel order.
|
||||
S3TC's weights are 0.082f, 0.6094f, 0.3086f in that order; maps are
|
||||
RGB4 {0,2,3,1}, RGB3 {0,2,1,3}. These are codec operations, not flag bits.
|
||||
- See [the coherent batch ledger](object_matching_logs/player_profile_s3tc_batch_reconciliation_20260907.md)
|
||||
for evidence limits, safe repairs, retained fuzzy work and exact debits.
|
||||
|
||||
Useful corroborating ledgers:
|
||||
|
||||
- [docs/object_matching_logs/damage_obj_object_damage_update_20260904.md](object_matching_logs/damage_obj_object_damage_update_20260904.md)
|
||||
documents project `real`, enum, flag, tick, and clamp use in a verified
|
||||
Damage owner.
|
||||
- [docs/object_matching_logs/bipeds_obj_jonas_disconnect_bsp_20260827.md](object_matching_logs/bipeds_obj_jonas_disconnect_bsp_20260827.md)
|
||||
records the January all-bits-set `NONE` representation in real object
|
||||
fields.
|
||||
- [docs/object_matching_logs/collision_bsp_obj_sphere_cluster_20260904.md](object_matching_logs/collision_bsp_obj_sphere_cluster_20260904.md)
|
||||
records a specifically authenticated byte-buffer/bit-vector boundary; it is
|
||||
an exception requiring evidence, not a blanket license for representation
|
||||
casts.
|
||||
@@ -1,35 +0,0 @@
|
||||
# January COMMON pool: ordering hypothesis and ownership limits
|
||||
|
||||
Lane C research, 2026-09-22; corrected during canonical reconciliation.
|
||||
|
||||
`linker_common.obj` is a synthetic split of tentative COMMON definitions.
|
||||
Several independently attributed records appear in contiguous clusters whose
|
||||
positions correlate with module order. This is useful as a **negative
|
||||
constraint**, but it does not prove the owner of an individual symbol.
|
||||
|
||||
Every pooled record in `config/contribs.json` resolves to synthetic module 847.
|
||||
The HCEX PDB lists these globals without a compiland. Declaration order and
|
||||
first-reference order do not reliably reproduce the pool order, either.
|
||||
Consequently, do not create a tentative definition merely because the symbol
|
||||
falls between two apparently owned records.
|
||||
|
||||
The original Lane C packet applied that inference too strongly. Canonical
|
||||
reconciliation excluded its 116-definition COMMON wave. An existing owner test
|
||||
reads January's split `rasterizer_frame_statistics` object, where its eponymous
|
||||
global appears only as an UNDEF external. That does **not** prove an import:
|
||||
csplit renders a pooled COMMON record as UNDEF (value 0) in a defining TU and in
|
||||
an importing TU alike, so the test cannot tell them apart and the owner of
|
||||
`_rasterizer_frame_statistics` remains **undetermined** (correction recorded
|
||||
2026-09-26; the test itself and its ownership checks are unchanged). The pool-order
|
||||
hypothesis does not settle it either. The same lack of
|
||||
independent proof affects `hs_syntax_data`, `ai_globals`, and
|
||||
`rasterizer_model_cortana_hack`; their Lane C moves were also not integrated.
|
||||
These are unresolved ownership questions, not credited reconstructions.
|
||||
|
||||
The useful, narrower rule remains: a genuine tentative definition must be
|
||||
uninitialised in source (`struct foo bar;`), while `= 0` or `= NULL` gives the
|
||||
symbol different COFF ownership. Compare both the January object and the
|
||||
rebuilt object's symbol class before accepting a declaration. The read-only
|
||||
`tools/campaign/linker_common_base.py` can inspect the known pool records, but
|
||||
its partial base earns **zero** matching credit under the all-or-nothing data
|
||||
metric. Its output must not be used as an ownership oracle.
|
||||
@@ -1,171 +0,0 @@
|
||||
# H1 tags cross-build intake (2026-09-06)
|
||||
|
||||
## Status and authority
|
||||
|
||||
The user supplied `C:/Users/isabe/Downloads/haloleak2024.rar`, specifically
|
||||
`halo1/h1_tags`. Five explicitly selected executables were extracted for local
|
||||
analysis. No executable was run and no tag assets were extracted. These inputs
|
||||
are **CROSSBUILD_ONLY** evidence, not the January 2002 Xbox target.
|
||||
|
||||
The user subsequently supplied the extracted folder
|
||||
`C:/Users/isabe/Downloads/haloleak2024/halo1/h1_tags`. All five symbol-executable
|
||||
SHA-256 hashes match the archive copies below exactly, so the saved analysis is
|
||||
reusable. The extracted `halo1` subtree also contains no PDB/DBG files at this
|
||||
checkpoint. The source folder remains read-only.
|
||||
|
||||
All five PE timestamps report 2020-11-23; their CodeView paths identify a
|
||||
`build/v140/Win32` build. A timestamp is a claim in the file, not independent
|
||||
build provenance. Each image has zero COFF symbols and zero exports. The
|
||||
CodeView records are **RSDS references to external PDBs**, not embedded PDB
|
||||
contents. The full archive listing contained 211,474 entries, no `.pdb` or
|
||||
`.dbg` files, and three `.map` files that are Halo 2 game assets rather than
|
||||
linker maps. Do not describe the `_symbols.exe` suffix as proof of a complete
|
||||
debug-symbol payload.
|
||||
|
||||
## Exact input identities
|
||||
|
||||
| Executable | Bytes | SHA-256 |
|
||||
| --- | ---: | --- |
|
||||
| `guerilla_symbols.exe` | 9,764,864 | `44538c3effe5a740f6995e7f6867995e81ec7d32ee8bb0bb74f04c2b9c203b83` |
|
||||
| `halo_cache_symbols.exe` | 6,672,896 | `740869688354defd295e28adf94bd4ea41385e9d4a98dc08764515285cf05b55` |
|
||||
| `halo_tag_symbols.exe` | 7,450,624 | `c5f58fe29cdde668d0e30f6848ad50b8f49a28e99c30de2b1bb75cf7bbfb0712` |
|
||||
| `sapien_symbols.exe` | 11,303,424 | `b1f0b207f5f49cb0ce90f5be7957197d3be612593ff52e7a50fc17e2b88a4828` |
|
||||
| `tool_symbols.exe` | 10,631,680 | `079d20d7792e9565b24ab2cff8115f76a6e48749a8e8ffd190f57954495f0a97` |
|
||||
|
||||
The missing PDBs must match **both GUID and age**, not just basename:
|
||||
|
||||
| PDB basename | GUID | Age (decimal) |
|
||||
| --- | --- | ---: |
|
||||
| `guerilla_symbols.pdb` | `9b751e93-d090-4fbf-9a7c-d8e3cbcb1866` | 125 |
|
||||
| `halo_cache_symbols.pdb` | `7f03f998-b7b0-4ea6-b18f-a6506e3442e5` | 14 |
|
||||
| `halo_tag_symbols.pdb` | `eac025b6-d3f8-4ae9-a47e-9882d7c58906` | 107 |
|
||||
| `sapien_symbols.pdb` | `82b677b3-b983-4c49-912e-ae5641ce5f76` | 87 |
|
||||
| `tool_symbols.pdb` | `3e2e627d-3e3b-4396-afd6-8ded91e9d954` | 80 |
|
||||
|
||||
## Local evidence and tools
|
||||
|
||||
Research root:
|
||||
`C:/Users/isabe/Documents/Codex/2026-07-13/i-w/research/symbol-build-h1-tags-20260906`
|
||||
|
||||
- `manifest.json`: PE sections, debug-directory records, exact PDB paths,
|
||||
identities, and explicit limits.
|
||||
- `inspect_builds.py`: regenerates the manifest using `pefile`, without
|
||||
executing or modifying the five input images.
|
||||
- `ghidra-scripts/CrossBuildInventory.java`: exports observed function names,
|
||||
their Ghidra source classification, and body ranges. It performs no renames.
|
||||
- `ghidra-projects/h1-tags-crossbuild.gpr`: new, separate cross-build project.
|
||||
- `ghidra-import.log`: successful automatic analysis and save of
|
||||
`halo_cache_symbols.exe` (187 seconds, no timeout).
|
||||
- `ghidra-import-remaining-retry.log`: the other four executables were imported
|
||||
and saved with `-noanalysis`. The already-imported cache executable was
|
||||
rejected as a duplicate and was **not overwritten**.
|
||||
- `ghidra-export-explicit-bundle.log` and
|
||||
`ghidra-export-cache-verified.log`: successful read-only inventory exports.
|
||||
Earlier export attempts failed independently of the saved imports. The
|
||||
explicit `ghidra-scripts/META-INF/MANIFEST.MF` and a subsequent run resolved
|
||||
script-bundle loading. The installed headless README names an unavailable
|
||||
timeout method; the installed Java source calls it `analysisTimeoutOccurred`.
|
||||
The inventory script now uses plain `GhidraScript`; analysis completion is
|
||||
established by the analysis log, not by a no-analysis export run.
|
||||
|
||||
Verified original-project status at the 2026-09-06 handoff (see the separate
|
||||
2026-09-07 analysis update below):
|
||||
|
||||
| Program | Analysis status | Observed function records |
|
||||
| --- | --- | ---: |
|
||||
| `halo_cache_symbols.exe` | Automatic analysis completed | 17,858 |
|
||||
| `halo_tag_symbols.exe` | Imported only; analysis pending | 18 |
|
||||
| `guerilla_symbols.exe` | Imported only; analysis pending | 5 |
|
||||
| `sapien_symbols.exe` | Imported only; analysis pending | 11 |
|
||||
| `tool_symbols.exe` | Imported only; analysis pending | 32 |
|
||||
|
||||
Function inventories are `<executable>.functions.tsv`. These counts include
|
||||
analysis-created functions/thunks and imports, **not recovered original Halo
|
||||
function counts**. Preserve each row's source classification and do not count
|
||||
names lacking a `FUN_` prefix as original symbols.
|
||||
For the analyzed cache executable, 17,525 records have Ghidra source `DEFAULT`,
|
||||
324 have `ANALYSIS`, and nine have `IMPORTED`; none establishes missing PDB
|
||||
contents. The `.gpr` file is a zero-byte project marker; its sibling `.rep`
|
||||
directory holds the databases and must stay with it.
|
||||
|
||||
The existing Ghidra installation was found by following its saved application
|
||||
log, not by assuming it was on PATH:
|
||||
`C:/Users/isabe/Documents/Codex/halo-tools/apps/ghidra_12.1.2_PUBLIC`.
|
||||
Its configured JDK is the sibling `jdk-21.0.11+10` directory. The live RPC
|
||||
endpoint at `127.0.0.1:18081` was offline at intake; the headless launcher is
|
||||
usable independently. Only Ghidra's local settings/cache directories needed
|
||||
additional write permission; the new project and outputs stay in the workspace.
|
||||
|
||||
IDA has not been located in the available tools, PATH, ordinary installation
|
||||
directories, registry installation entries, or the local Halo tool bundle.
|
||||
**The user's requirement to use both IDA and Ghidra remains outstanding.** Do
|
||||
not claim that Ghidra, Capstone, or a PE parser satisfies the IDA half. A usable
|
||||
installation/license or further location evidence is needed. Do not upload
|
||||
these inputs to a cloud decompiler or symbol service without authorization.
|
||||
|
||||
Keep the executables, databases, and generated bulk inventories local. This
|
||||
ledger records pointers and hashes only; it is not authorization to publish
|
||||
the supplied binary corpus.
|
||||
|
||||
## Reconstruction plan and limits
|
||||
|
||||
1. Identify the source build and validate any future PDB against the recorded
|
||||
GUID/age before loading its names/types into its own donor database.
|
||||
2. Preserve evidence categories: imported API names, disassembler inference,
|
||||
diagnostic literals, genuine debug records, and independently January-proven
|
||||
facts are different things. A generated `FUN_...` name is not an original
|
||||
name and must not become a production `code_<address>` substitute.
|
||||
3. Use diagnostic strings, callers, data references, and instruction/CFG
|
||||
comparisons to propose January correspondences. Verify each mapping locally;
|
||||
never add one global address delta across builds.
|
||||
4. "Un-inline" means recover and annotate candidate helper operations and their
|
||||
call-site relationships where evidence permits. It cannot recreate all lost
|
||||
source, local variables, or original inline boundaries. Do not rewrite the
|
||||
January target, force new calls, or emit a `point_from_line3d` COMDAT to make
|
||||
the donor's decompilation look tidier.
|
||||
5. Names and types can accelerate source reconstruction, but exact credit still
|
||||
requires the January COFF byte/relocation, source-authenticity, whole-TU,
|
||||
whole-tree regression, and object-admission gates. No canonical code bytes
|
||||
are earned by this intake or by automatic analysis alone.
|
||||
|
||||
## 2026-09-07: seven further programs analyzed and saved
|
||||
|
||||
The original project/cache analysis above remains preserved. A separate project
|
||||
now holds the four remaining Symbols programs and the three supplied Play
|
||||
programs:
|
||||
`C:/Users/isabe/Documents/Codex/2026-07-13/i-w/research/hs7/remaining-projects/h1-tags-remaining-seven.gpr`.
|
||||
Keep its sibling `.rep` directory with it. No supplied executable was run.
|
||||
|
||||
All seven Programs were saved and 21 detailed exports were produced. Input
|
||||
hashes and exported PDB GUID/ages were rechecked. The bounded analysis phases
|
||||
finished with warnings for Halo Tag Symbols (19,228 function records), Sapien
|
||||
Symbols (54,820), Guerilla Play (3,770), Sapien Play (9,045) and Tool Play
|
||||
(7,893). Guerilla Symbols (41,854) and Tool Symbols (46,630) reached their
|
||||
300-second limits and remain explicitly **partial**, not complete analyses.
|
||||
|
||||
The local guide is `research/hs7/ANALYSIS_GUIDE.md` under the outer workspace;
|
||||
the detailed functions/types/metadata exports are in `research/hs7/analyze-detailed`.
|
||||
`research/hs7/remaining-analysis-summary.json` has SHA-256
|
||||
`dbe1283d88ae4b8839b42888e7f80d70be4a87233824a99f7c6a77540bae5aaa`.
|
||||
The guide records source classifications, timeout evidence, API-type archive
|
||||
provenance and analyzer warnings, including WindowsResourceReference's OSGi
|
||||
warning. PDB analyzers were disabled because matching PDBs are absent; no
|
||||
external symbol download was performed. These generated records are not
|
||||
restored original names, inline boundaries or debug assets, and earn no exact
|
||||
code credit. IDA remains unlocated and that part of the request is outstanding.
|
||||
|
||||
## Related networking evidence
|
||||
|
||||
[Exploring The Halo 1 System Link Protocol](https://hllmn.net/blog/2023-09-18_h1x-net/)
|
||||
provides retail PAL packet/debugger evidence. Its decoded advertisement retains
|
||||
the suffix `age in a bot`. This corroborates, but does not independently prove
|
||||
for January, our source-attested join-token implementation: the first four
|
||||
bytes are transformed while the remaining twelve survive. The article's
|
||||
two-second search cadence is another comparison lead. Its PAL timing and
|
||||
absolute addresses must not replace January constants or addresses.
|
||||
|
||||
Use the article's emulator-boundary inspection method as a future local
|
||||
runtime-validation aid. No live interception or traffic manipulation was
|
||||
performed for this intake. The canonical token implementation and runtime tests
|
||||
are documented in
|
||||
`docs/object_matching_logs/network_server_manager_obj_source_attested_packet_20260906.md`.
|
||||
@@ -1,374 +0,0 @@
|
||||
# Exact-match acceleration playbook
|
||||
|
||||
This document records techniques with broader application to the January 2002
|
||||
Halo Xbox decompilation. Object-specific measurements remain in
|
||||
`docs/object_matching_logs/`; this file contains only controls, triage rules,
|
||||
and campaign practices that have survived strict comparison.
|
||||
|
||||
The objective is faster reconstruction without lowering the bar. A candidate
|
||||
is not exact because it is correct, similar, the same size, or 99% fuzzy. The
|
||||
admission evidence remains XDK 3911 output, exact normalized bytes, exact
|
||||
relocation shape and resolved destinations, exact owned data/layout, and a
|
||||
whole-translation-unit regression audit.
|
||||
|
||||
## Campaign strategy
|
||||
|
||||
1. **Finish objects, not isolated functions.** Prefer a unit with a bounded
|
||||
residual and known data ownership over a larger number of unrelated leaves.
|
||||
Once an object is opened, carry it through code, data, ownership, regression,
|
||||
documentation, and `Matching` admission unless a measured compiler tie
|
||||
satisfies the parking standard.
|
||||
2. **Prioritize reusable foundations.** Scenario/BSP accessors, real-math
|
||||
leaves, player/unit layouts, tag/object accessors, datum iterators, compiler
|
||||
wrapper families, and complete donor translation units reduce later work.
|
||||
3. **Separate reconstruction from tuning.** First recover the January
|
||||
semantics, types, call graph, private ABI, and owned data. Tune source shape
|
||||
only after target size/relocation evidence says the structure is close.
|
||||
4. **Work atomic private-ABI clusters together.** Static helpers and their
|
||||
callers can form a register-allocation fixed point. Splitting them across
|
||||
lanes produces false blockers.
|
||||
5. **Use a bounded experiment budget.** Test one source factor at a time,
|
||||
record the exact result, and stop repeating compiler-equivalent spellings.
|
||||
A parked result needs explicit size, relocation, first-divergence, and
|
||||
exhausted-control evidence.
|
||||
6. **Automate candidate generation, never acceptance.** Shape-transfer and
|
||||
donor tools may propose source, but the unchanged strict comparator and
|
||||
regression gates decide admission.
|
||||
|
||||
### Select closeouts from strict evidence, not the ordinary percentage
|
||||
|
||||
Run `python -m tools.rank_object_closeouts` after regenerating the ordinary
|
||||
and semantic reports. The ranking deliberately combines:
|
||||
|
||||
- the complete function inventory from the ordinary report;
|
||||
- the reviewed strict `accepted_ledger`;
|
||||
- object `Matching` status; and
|
||||
- the evidence-backed parked-function catalog.
|
||||
|
||||
This prevents three recurring campaign mistakes:
|
||||
|
||||
1. treating a differently numbered local jump-table label as unfinished code;
|
||||
2. repeatedly dispatching a one-function object whose only residual is already
|
||||
a proven compiler tie; and
|
||||
3. overlooking a data-only closeout after every function is exact.
|
||||
|
||||
The tool is a triage aid, not an admission oracle. `NEAR_CLOSEOUT` means the
|
||||
remaining work is unparked and bounded; it does not predict that source tuning
|
||||
will succeed. `LEDGER_REVIEW` means earlier object work exists and its
|
||||
do-not-repeat/reopen rules must be read before dispatch. `PROVEN_BLOCKED` means
|
||||
every remaining function is in the
|
||||
reviewed parked ledger and must not be reopened without satisfying its stated
|
||||
reopen criterion. Always read the object's Markdown ledger before editing.
|
||||
|
||||
## Evidence hierarchy
|
||||
|
||||
From strongest to weakest:
|
||||
|
||||
1. January target bytes, relocation metadata, linked addresses, and section
|
||||
ownership.
|
||||
2. January sibling functions and exact donor translation units.
|
||||
3. January assert strings, source paths, help tables, tag definitions, and call
|
||||
sites.
|
||||
4. XDK 3911 headers and synthetic compiler experiments under the exact flags.
|
||||
5. October Xbox, Halo PC/CEA/HCEX PDBs, community forks, and later-engine types.
|
||||
|
||||
Levels 4 and 5 generate hypotheses. They do not override January evidence.
|
||||
Every imported field, enum, prototype, or name must be corroborated locally.
|
||||
|
||||
## High-yield source controls
|
||||
|
||||
### Ownership and alias modeling
|
||||
|
||||
VC7 code generation depends on what it can prove about globals:
|
||||
|
||||
- Aggregate storage can force address common-subexpression elimination or
|
||||
destroy an index because sibling fields may alias.
|
||||
- Separate globals can preserve a live SIB index and eliminate reloads.
|
||||
- A one-field structure can retain field-oriented optimizer behavior while a
|
||||
separate array supplies non-aliasing proof. This closed
|
||||
`game_engine_multiplayer_sounds.obj`: it preserved `dec; mov; je` flags in
|
||||
the update while producing SIB stores in the queue helper.
|
||||
- Static versus external linkage affects alias knowledge, section order,
|
||||
symbol storage class, and whether zero-initialized data becomes `.bss` or a
|
||||
tentative/common symbol.
|
||||
|
||||
Always verify the full object. A linkage change can leave every function exact
|
||||
while silently deleting or reordering `.bss`.
|
||||
|
||||
### Statement and branch order
|
||||
|
||||
- VC7 often reflects the original failure-first versus success-first topology.
|
||||
Reversing an `if` can fix multiple relocation-address regions at once.
|
||||
- Tail-merging is sensitive to deliberately asymmetric source duplication.
|
||||
If two switch cases must share a forward machine-code tail but an explicit
|
||||
shared label sinks a callee-save or changes the prologue, keep the simple
|
||||
early path's tiny terminal test locally and route the longer path forward to
|
||||
the other case's copy. In `shaders.obj`, VC7 cross-jumped that readable
|
||||
duplicate into one shared target tail while preserving the required ESI
|
||||
lifetime. Verify relocation identities: this is a measured block-placement
|
||||
control, not permission to duplicate arbitrary logic.
|
||||
- Common stores in two branches may be tail-merged, but a constant-valued
|
||||
branch can instead materialize an immediate store and grow the function.
|
||||
- Comparison polarity matters even when predicates are logically equivalent;
|
||||
it controls `cmp` operand order, signed branches, and register lifetimes.
|
||||
- Use a single return when the target structure permits it. When the exact
|
||||
source requires multiple source returns to reproduce a common compiler
|
||||
epilogue, record that as an evidence-backed house-style exception.
|
||||
|
||||
### Scalar stores versus aggregate operations
|
||||
|
||||
- Field-wise stores give the scheduler independent operations and can reproduce
|
||||
interleavings that `{0}`, aggregate assignment, `memset`, or `rep stos`
|
||||
cannot.
|
||||
- Conversely, aggregate assignment is useful when the target uses `rep movs`
|
||||
or a single calculated element address.
|
||||
- VC7 groups local-struct zero initialization by brace level. If member zero
|
||||
is itself an aggregate, `= {0}` can produce one whole-struct zero live range,
|
||||
while `= {{0}}` can split the first member's fill from the implicit trailing
|
||||
fill. A target whose zero stores split exactly at that member boundary is
|
||||
evidence for testing the extra brace; this closed
|
||||
`telnet_console_initialize` without changing behavior.
|
||||
- Preserve target load and store order before trying declaration-order noise.
|
||||
|
||||
### Local lifetime is more important than local spelling
|
||||
|
||||
Naming an expression does not necessarily change VC7 output; the optimizer can
|
||||
fold a short-lived alias immediately. What matters is where the value becomes
|
||||
live and how long it must survive. In `data_packets.obj`, naming
|
||||
`decoded_data + sizeof(short)` beside its final memory call did nothing across
|
||||
several experiments. Computing the same readable payload pointer *before* the
|
||||
range assert and keeping it live across validation plus an intervening integer
|
||||
encode changed no instruction by itself, but rotated three later scratch
|
||||
registers and closed a 768-byte function exactly.
|
||||
|
||||
In plain English: do not keep renaming a value and expect different code. Move
|
||||
the point where the program genuinely needs to remember it, then measure the
|
||||
whole function. This is especially useful around asserts and calls, where an
|
||||
additional live pointer changes the compiler's interference graph without
|
||||
inventing operations.
|
||||
|
||||
### Integer width and signedness
|
||||
|
||||
- `movsx`/`movzx`, partial-register operations, and signed branch opcodes reveal
|
||||
the real promotion boundaries.
|
||||
- Function parameter widths matter even when the x86 ABI still occupies a
|
||||
four-byte stack slot. In `rasterizer_xbox_motion_sensor.obj`, changing a
|
||||
render-target parameter from `long` to the proven `word` transformed
|
||||
`movzx` into the target's `xor reg, reg; mov reg16, [memory]` sequence and
|
||||
closed the entire remaining half of a 1,920-byte function.
|
||||
- Change signedness only where the target proves it. A `jle` versus `jbe`
|
||||
difference is often a type error; an ESI/EDI mirror is not.
|
||||
- Recover narrow accumulators instruction by instruction rather than relying
|
||||
on C's default integer promotions.
|
||||
|
||||
### x87 controls
|
||||
|
||||
- A value live after a store selects `fst`; a dead value selects `fstp`.
|
||||
- Source operand order controls non-commutative subtraction/division memory
|
||||
forms. VC7 canonicalizes commutative addition/multiplication; spelling order
|
||||
is not a lever there.
|
||||
- Passing, returning, or globally storing a floating result produces distinct
|
||||
stack-staging patterns.
|
||||
- Never substitute mathematically equivalent expressions that change signed
|
||||
zero, NaN payload/sign, intermediate precision, or rounding.
|
||||
- When a shared inline vector helper matches standalone but changes scheduling
|
||||
at one caller, preserve the donor's **expression surface**, including
|
||||
apparently redundant parentheses. In `collision_features.obj`, changing
|
||||
`(v->i*t) + p->x` to the equally readable `v->i*t + p->x` altered inline IR
|
||||
without changing the helper's standalone meaning and restored a January
|
||||
`fstp`/address-formation boundary. Treat this as a measured inline-context
|
||||
lever, not a license for blind parenthesis permutations.
|
||||
- VC7 reassociates a one-expression commutative dot product, so merely reversing
|
||||
its written terms may do nothing. If January proves a specific x87 load/add
|
||||
order, sequential accumulation can preserve it. The exact
|
||||
`collision_prism_test_vector` form initializes the `k` product, then adds
|
||||
`j`, then `i`; every intermediate remains a normal `real` value.
|
||||
|
||||
### XDK inline wrappers
|
||||
|
||||
Stock XDK `D3DINLINE` under this compiler emits the January out-of-line D3D
|
||||
wrapper families when called normally. Address-taking forces a different
|
||||
standard-ABI body, and redefining `D3DINLINE` as plain `static` can emit a
|
||||
thunk. Prefer the stock header form and verify every emitted wrapper in the TU.
|
||||
One motion-sensor translation unit instantiated ten such wrappers exactly in a
|
||||
single build, including both 432-byte and 544-byte dispatchers. Treat the
|
||||
header recipe as a high-yield candidate generator, but still compare every
|
||||
wrapper and its relocation destinations independently.
|
||||
|
||||
### Diagnose the first true divergence
|
||||
|
||||
- Ignore downstream branch displacements and relocation-address drift until
|
||||
the earliest semantic or instruction-length difference is closed.
|
||||
- Decode cdecl pushes right-to-left before blaming register allocation. A wrong
|
||||
argument order can make a large suffix look like a scheduler problem.
|
||||
- If a small type correction makes a long suffix exact automatically, the
|
||||
suffix was displacement drift, not a collection of independent problems.
|
||||
- Zero-byte intrinsics such as `_ReadWriteBarrier()` are measured controls, not
|
||||
universal fixes. They can prevent desirable argument hoisting and make an
|
||||
otherwise close function worse.
|
||||
- A one-byte `push eax` where the reconstruction emits the two-byte `push 0`
|
||||
after testing a result is evidence that the original passes the tested
|
||||
result, not a literal. Preserving that value into the error arm can change a
|
||||
large register-allocation suffix even when alignment leaves the padded size
|
||||
unchanged. For size-exact functions containing a switch, inspect padding
|
||||
and jump-table tails as well as the nominal body.
|
||||
|
||||
### Recover the type before tuning the schedule
|
||||
|
||||
A value that stays live in a register longer than expected is often evidence
|
||||
of a wrong prototype or field width, not a mysterious compiler decision.
|
||||
Before trying declaration orders, barriers, or control-flow rewrites:
|
||||
|
||||
- Check what the target returns in `EAX` or `AL`. If the target preserves a
|
||||
meaningful value until `ret`, a function currently declared `void` may
|
||||
actually return that value.
|
||||
- Check whether the target consistently reads, masks, or writes only the low
|
||||
byte or low word. A `char`, `boolean`, `short`, or `word` may be the real
|
||||
type even when a 32-bit placeholder produces correct gameplay behavior.
|
||||
- Prefer the smallest type that is supported by all call sites and target
|
||||
instructions. Do not narrow a type merely because it happens to improve the
|
||||
bytes.
|
||||
|
||||
In `texture_page.obj`, recovering `spacing_mask` as a 16-bit `word` made a
|
||||
736-byte packing function exact. Recovering
|
||||
`texture_page_textures_end` as a `boolean` function explained why January kept
|
||||
the packing result in `AL` across the loop and made its remaining 112 bytes
|
||||
exact. In plain English: the compiler was not being stubborn; we had told it
|
||||
the wrong facts about the program.
|
||||
|
||||
### Private ABI controls
|
||||
|
||||
A source-static, non-address-taken, frameless helper can receive arguments in
|
||||
ECX/EDX or another caller-derived convention. External linkage, address-taking,
|
||||
or a stack frame can destroy that convention. Work from a forced-register
|
||||
caller outward; do not tune a private helper in isolation.
|
||||
|
||||
### Compiler provenance before compiler hunting
|
||||
|
||||
Do not attribute a stubborn register or scheduling residual to an unknown
|
||||
compiler patch until the target's own debug records have been checked.
|
||||
PDB 2.00 module streams can contain `S_COMPILE2_ST` records with independent
|
||||
front-end and back-end version triples. For the January `players.obj`, the
|
||||
record proves `13.0.9254` for both halves, matching the campaign compiler's
|
||||
reported build.
|
||||
|
||||
Use this order:
|
||||
|
||||
1. Decode the target compiland's compiler record.
|
||||
2. Compile the unchanged TU once with each genuinely distinct local compiler
|
||||
binary.
|
||||
3. Compare normalized hashes for every residual, not just the first
|
||||
instruction.
|
||||
4. If all variants are byte-identical, stop the compiler hunt and return to
|
||||
source provenance or a demonstrated legal-C control.
|
||||
|
||||
For Players, VC7 `13.00.9210` and `13.00.9254.1` emitted byte-identical
|
||||
candidate hashes for all four residuals. That falsifies the available
|
||||
patch-level lever and prevents repeated SDK downloads or speculative flag
|
||||
changes.
|
||||
|
||||
## Transfer and donor rules
|
||||
|
||||
- A donor is usable only when its source text is resolved and its target
|
||||
machine shape is exact.
|
||||
- Derive every recipient callee/global substitution from the recipient target
|
||||
relocations, never by name similarity.
|
||||
- Equal relocation-masked bytes can hide a wrong-callee wrapper. Destination
|
||||
identity and addends remain strict.
|
||||
- Preserve target statement order; relocation sequence is often its strongest
|
||||
surviving proof.
|
||||
- Reject stubs, unresolved donors, inconsistent substitution maps, prologue
|
||||
mismatches, and data-ownership changes automatically.
|
||||
|
||||
### Candidate-only helper COMDATs
|
||||
|
||||
An inlined helper can occasionally leave an unreferenced out-of-line COMDAT
|
||||
copy in the candidate object. Never dismiss it just because the target
|
||||
function compares equal. It is acceptable only after all of the following are
|
||||
proved:
|
||||
|
||||
- the extra section is a discardable COMDAT with the expected selection rule;
|
||||
- no relocation in the object refers to it;
|
||||
- every target-owned function and data section remains strict-exact;
|
||||
- the ordinary link actually discards it; and
|
||||
- the consolidated link, semantic audit, and progress report remain clean.
|
||||
|
||||
This is a linker-level representation difference, not permission to ignore
|
||||
extra ordinary code or data.
|
||||
|
||||
## Parking standard
|
||||
|
||||
Park only when:
|
||||
|
||||
- target and candidate padded size are exact;
|
||||
- relocation count, types, and destinations are exact, or a reviewed
|
||||
representation-only difference has independently resolved destinations;
|
||||
- the remaining divergence is classified precisely;
|
||||
- legal-C controls appropriate to that class have been exhausted;
|
||||
- the object ledger records a reproducible first divergence and reopen
|
||||
criterion.
|
||||
|
||||
A 92% function with different size or relocations is structural work, not a
|
||||
compiler tie. A one-instruction scheduler swap can be parked only after the
|
||||
dependency and source-control search are documented.
|
||||
|
||||
## Admission checklist
|
||||
|
||||
Before marking an object `Matching`:
|
||||
|
||||
1. Build with XDK 3911 and the repository flags.
|
||||
2. Compare every function with the hardened COFF comparator.
|
||||
3. Verify every owned `.data`, `.rdata`, and `.bss` span, including symbol
|
||||
offsets, storage classes, and relocation destinations.
|
||||
4. Confirm the ordinary report does not hide a strict false positive.
|
||||
5. Run the whole-TU regression gate against a pre-edit snapshot. Review every
|
||||
intentional ownership transition; never suppress unrelated failures.
|
||||
6. Run the consolidated build, semantic audit, and progress report.
|
||||
7. Update the object ledger with retained and rejected experiments.
|
||||
8. Mark `Matching` only after all evidence passes.
|
||||
|
||||
### Greenfield regression gates
|
||||
|
||||
An empty skeleton has no previously exact code or owned data for a pre-edit
|
||||
manifest to protect. A correct reconstruction will therefore appear to the
|
||||
regression gate as a set of new functions, symbols, COMDATs, and data. Do not
|
||||
force that report green and do not waive its findings:
|
||||
|
||||
- confirm that it reports no changed previously exact function or section;
|
||||
- classify every addition against the January target;
|
||||
- admit the object only after strict function, relocation, ownership,
|
||||
consolidated-build, and semantic-progress checks pass;
|
||||
- immediately capture a post-admission manifest and verify it is stable, so
|
||||
later edits are checked against the newly completed object.
|
||||
|
||||
## Original bugs
|
||||
|
||||
Exact reconstruction preserves proven original behavior. Mark a defect
|
||||
`BUG (original)` only when January evidence proves it. In the matching source,
|
||||
retain the original behavior and add a concise comment describing a safe
|
||||
corrected-build alternative. Do not silently repair it and do not label our
|
||||
own reconstruction mistake as an original bug.
|
||||
|
||||
An original uninitialized read is an exceptional case, not a general codegen
|
||||
lever. Preserve one only when the January control flow proves the read, an
|
||||
independent build or source lineage corroborates it, and a bounded search shows
|
||||
that defined readable-C alternatives do not match. Record the safe initialized
|
||||
form and its measured result in the object log. Never introduce a new
|
||||
uninitialized value merely because it improves register allocation.
|
||||
|
||||
Do not infer a fallback assignment merely because target code reloads a value
|
||||
after a fatal assertion or `system_exit`. In `data_decode_memory`, that
|
||||
seemingly sensible repair was the sole cause of a whole-function register
|
||||
allocation mismatch; the January/October machine code plus an exact-unique
|
||||
HCEA PDB local record and HCEA PPC body showed that the original impossible
|
||||
default arm left its sole size local unassigned. Remove such a repair only
|
||||
with the full original-bug evidence gate above, then state the safe corrected
|
||||
alternative in source and measure it in the object log.
|
||||
|
||||
## Prohibited shortcuts
|
||||
|
||||
No inline assembly, volatile byte forcing, undefined aliasing, object-byte
|
||||
patches, compiler pragmas used only to force bytes, flag changes, fuzzy-only
|
||||
credit, or invented symbols/types. Compiler experiments belong in disposable
|
||||
worktrees; production admission must remain readable evidence-backed C.
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
# Fake-match source review
|
||||
|
||||
`tools/fake_match_scan.py` finds unusual C/C++ constructs that deserve a
|
||||
credibility or semantics review. It is a heuristic lead generator, not an
|
||||
object comparator, admission gate, or proof that source is fake. A byte match
|
||||
does not make nonsensical source credible, and a scanner hit does not make
|
||||
ordinary source wrong.
|
||||
|
||||
These examples run from the repository root (the script also derives the
|
||||
repository root correctly when invoked by an absolute path from elsewhere):
|
||||
|
||||
```text
|
||||
python tools/fake_match_scan.py
|
||||
python tools/fake_match_scan.py source/ai/actions.c source/game
|
||||
python tools/fake_match_scan.py --format json --fail-on-findings source/ai
|
||||
python tools/fake_match_scan.py --list-rules
|
||||
```
|
||||
|
||||
The default input is the repository's `source/` directory. Explicit file and
|
||||
directory inputs are de-duplicated and emitted in deterministic path/line/rule
|
||||
order. Known vendored libtiff, zlib, `third_party`, and `vendor` trees are
|
||||
skipped unless `--include-vendored` is supplied. Comments and string/character
|
||||
literals are masked before scanning so examples and assert text do not become
|
||||
findings.
|
||||
|
||||
Exit status is deterministic:
|
||||
|
||||
- `0`: the scan completed; findings may be present.
|
||||
- `1`: findings are present and `--fail-on-findings` was requested.
|
||||
- `2`: an input is invalid or a source file cannot be read.
|
||||
|
||||
Every finding should prompt a source review, not an automatic rewrite. Check
|
||||
whether the construct expresses plausible original program intent, whether the
|
||||
logic is meaningful for all inputs, and whether first-party source, names,
|
||||
target CFG/relocations, or a credible contemporary codebase supports it. Re-run
|
||||
the strict object and regression gates after any resulting edit. Exact bytes
|
||||
alone are not provenance.
|
||||
|
||||
Semantic validity is an admission requirement even when every byte matches.
|
||||
Reject code whose behavior is nonsensical, whose conditions or data flow are
|
||||
meaningless, or whose source shape almost certainly would not have existed in
|
||||
the original program. A coincidental exact result must be reverted or replaced
|
||||
with the best honest fuzzy reconstruction and parked with its evidence.
|
||||
|
||||
The rule set intentionally omits several noisy shortcuts. It does not condemn
|
||||
ordinary `volatile` declarations, generic representation casts, `!!value`, or
|
||||
`value != value`; those can express hardware synchronization, serialization,
|
||||
boolean normalization, or a NaN test. It also performs no data-flow proof, so a
|
||||
clean scan cannot establish that variables are initialized or that logic is
|
||||
sound.
|
||||
@@ -1,63 +0,0 @@
|
||||
# source/linker_common: what a comparison base can and cannot earn
|
||||
|
||||
*2026-09-22, Lane C. Built at the owner's direction, from January's verified
|
||||
COMMON records only, and scored separately from the board.*
|
||||
|
||||
## What the unit is
|
||||
|
||||
`source/linker_common` is not a translation unit. It is csplit's name for the
|
||||
pooled COMMON block of January's image: 242 records totalling 1,272,664 bytes,
|
||||
gathered by the linker from tentative definitions across the whole program
|
||||
(`_render` 643,732, `_ai_debug` 547,628, `_dsound_globals` 30,924, and ~200
|
||||
smaller ones, down to single-byte debug toggles). `objdiff.json` gives it a
|
||||
`target_path` and **no `base_path`**, because our build produces no such object -
|
||||
our COMMON symbols live in their owning objects' symbol tables with section 0.
|
||||
So it reports 0.000% structurally, not because anything is wrong.
|
||||
|
||||
## The base, and its score
|
||||
|
||||
`tools/campaign/linker_common_base.py` builds a comparison base containing ONLY
|
||||
verified records: a symbol January pools that our tree independently emits as a
|
||||
COMMON symbol of the identical size. Nothing is invented, and nothing
|
||||
initialised is copied - a `.bss` record carries no bytes, only a name and a
|
||||
size, and the size used is the one our own objects request. Records we do not
|
||||
emit, emit at a different size, or emit in a real section are dropped.
|
||||
|
||||
kept 58 records 1,214,903 bytes
|
||||
dropped 184 records 56,787 bytes
|
||||
|
||||
Scored on its own (`objdiff-cli report generate` over a one-unit config):
|
||||
|
||||
.bss 1,272,568 95.541%
|
||||
.rdata 96 0.000%
|
||||
credited 0
|
||||
|
||||
**It earns nothing.** Data is credited per section only at 100%, so 95.541% is
|
||||
worth exactly as much as 0%. The number's value is diagnostic: it says 95.5% of
|
||||
the pooled block is already correct in our tree, and names precisely what is not.
|
||||
|
||||
## What the remaining 4.5% is
|
||||
|
||||
181 records, 56,187 bytes, absent from our tree entirely. Only 27 of them
|
||||
(1,125 bytes) are CRT/XDK/dsound runtime symbols. The rest are genuine Halo
|
||||
globals no TU of ours declares: `_dsound_globals` 30,924, `_rasterizer_lights`
|
||||
7,172, `_sound_channels` 6,144, `_wind_globals` 3,340, `_error_globals` 2,056,
|
||||
`_global_window_parameters` 600, and so on. Plus two pooled `.rdata` records
|
||||
(96 bytes) that are not COMMON at all and so are outside this base by
|
||||
construction, and one size mismatch, `_file_location_volume_names`, which is the
|
||||
out-of-bounds array bug recorded separately.
|
||||
|
||||
Closing the section therefore needs those 181 globals declared as tentative
|
||||
definitions in the right units - spread across many TUs, several of which are
|
||||
not reconstructed - and it pays nothing until every one of them is present.
|
||||
|
||||
## Rules this establishes
|
||||
|
||||
* A symbol in `linker_common` was a TENTATIVE DEFINITION in January: declared
|
||||
with no initialiser. **Never add `= {0}` to such a global** - that moves it out
|
||||
of the pool. Check `linker_common` before touching any global's initialiser.
|
||||
This is how the `actors.c` `= NULL` defect was found and fixed.
|
||||
* Conversely, a global January keeps in its OWN object's `.bss` (director,
|
||||
render_objects) was initialised in source, and must keep its initialiser.
|
||||
* Do not wire this base into `objdiff.json`. It would fold a structurally
|
||||
uncreditable section into the board number without closing anything.
|
||||
@@ -1,178 +0,0 @@
|
||||
# Exact-matching methodology
|
||||
|
||||
This document records recurring January 2002/XDK 3911 matching failures and
|
||||
the source-level changes that have actually moved them. It is an operational
|
||||
checklist, not permission to accept approximate code. Exact status still
|
||||
requires padded bytes, normalized bytes, relocation count/type/address/target/
|
||||
addend, ABI, build, and regression evidence.
|
||||
|
||||
## Triage decision tree
|
||||
|
||||
Before guessing literals or reconstructing diagnostics, consult the
|
||||
[common constants reference](common_constants.md) and
|
||||
[shared assertion API](assertions.md). They identify existing owners and
|
||||
target-specific representation pitfalls; they do not authorize numeric or
|
||||
source-shape substitutions just because a value looks familiar.
|
||||
|
||||
1. Establish the untouched baseline: padded size, meaningful size, normalized
|
||||
hash, relocation table, first differing instruction, and sibling status.
|
||||
2. If relocation targets or addresses differ, recover source structure before
|
||||
tuning registers: statement order, branch fall-through, linkage, field
|
||||
ownership, and eager versus lazy evaluation.
|
||||
3. If the target uses 16-bit arithmetic, map every promotion and truncation
|
||||
boundary. Treat this separately from register allocation.
|
||||
4. If instruction structure is identical modulo registers, locate a
|
||||
hardware-forced anchor before changing declarations:
|
||||
- `rep movs`/`rep stos` force ESI, EDI, and ECX;
|
||||
- variable shifts force CL/ECX;
|
||||
- multiply and divide force EAX/EDX;
|
||||
- ABI/API boundaries may force ECX/EDX or preserve callee-saved registers.
|
||||
5. For private same-translation-unit helpers, make callers exact first. Start
|
||||
from the hardware-forced caller and propagate the convention toward the
|
||||
helper; do not tune the helper in isolation.
|
||||
6. Stop after five evidence-based source shapes if only an interchangeable
|
||||
register or dependency-free instruction ordering remains. Record and park
|
||||
the case instead of perturbing unrelated exact code.
|
||||
7. Run the strict semantic ledger before assigning work. A function already
|
||||
listed in `build/semantic_report.json` must not be reimplemented merely
|
||||
because objdiff displays a fuzzy percentage.
|
||||
8. When a target macro or expression is known from an exact donor, preserve
|
||||
its **lvalue topology** as well as its arithmetic. VC7 can emit different
|
||||
code for mathematically equivalent forms such as transforming a temporary
|
||||
and transforming the destination member in place. Prefer the donor's
|
||||
assignment destination, member access, and read-back pattern before
|
||||
permuting commutative terms or adding artificial temporaries.
|
||||
|
||||
## Source-credibility gate
|
||||
|
||||
An exact object is necessary evidence, but exact bytes alone do not make a
|
||||
reconstruction admissible. Retained source must express coherent program logic
|
||||
and remain plausible for the original January 2002 codebase. Reject inert,
|
||||
contradictory, undefined, or artificial source whose only credible purpose is
|
||||
to steer VC7 into the target byte sequence. This includes unexplained empty
|
||||
branches, self-assignments, fixed conditions, volatile or aliasing tricks,
|
||||
synthetic lifetime anchors, raw instruction emission, and compiler-control
|
||||
directives. A target-proven original bug is the narrow exception and must meet
|
||||
the original-bug policy below.
|
||||
|
||||
Review semantics across all reachable inputs, not only the path that resembles
|
||||
the disassembly. Corroborate unusual topology with January code/data/relocation
|
||||
evidence, authenticated names or type records, first-party source, or a
|
||||
credible contemporary analogue such as Marathon. When ordinary, meaningful C
|
||||
does not reach exactness after the bounded methodology, retain the best honest
|
||||
fuzzy reconstruction, record the residual, and park it.
|
||||
|
||||
`python tools/fake_match_scan.py` provides conservative lexical review leads
|
||||
for several common smells. Its findings are neither proof of fake source nor a
|
||||
substitute for manual semantic and provenance review, and a clean scan is not
|
||||
proof of credibility.
|
||||
|
||||
## Blocker classes
|
||||
|
||||
### A. Recoverable source-shape mismatch
|
||||
|
||||
The emitted differences indicate that the reconstructed C is not yet shaped
|
||||
like the original source. Productive levers include statement order, branch
|
||||
polarity, local lifetime, explicit versus inlined expressions, linkage, and
|
||||
structure ownership.
|
||||
|
||||
### B. Integer promotion/truncation mismatch
|
||||
|
||||
The target contains operand-size prefixes, partial-register operations, or
|
||||
`movsx`/`movzx` boundaries that ordinary C promotions erase. Recover the width
|
||||
of the accumulator and place signed/unsigned casts only at disassembly-proven
|
||||
boundaries. Do not file this as a register mirror.
|
||||
|
||||
### C. Private-ABI/register fixed point
|
||||
|
||||
The instruction graph, sizes, and relocations agree, but a translation-unit
|
||||
cluster assigns interchangeable registers differently. Find a forced-register
|
||||
caller and solve outward. If the complete cluster remains a pure permutation
|
||||
after the checklist, park it as a compiler allocation tie.
|
||||
|
||||
### D. Scheduler/lifetime tie
|
||||
|
||||
Two dependency-free instructions are transposed, or local lifetimes alter
|
||||
spills without changing semantics. Try only source changes justified by the
|
||||
surrounding target ordering. Do not add undefined behavior, inline assembly,
|
||||
compiler pragmas, or flag changes to force the result.
|
||||
|
||||
### E. Comparator/reporting mismatch
|
||||
|
||||
The machine code is exact but COFF producers encode internal labels or
|
||||
relocation placeholders differently. Credit only through the hardened
|
||||
semantic comparator and the reviewed `config/semantic_matches.json` allowlist;
|
||||
each entry is reverified against current objects during `ninja progress`.
|
||||
|
||||
### F. Credible but unclassified residual
|
||||
|
||||
The retained source can be semantically and historically grounded even when
|
||||
the fail-closed classifier cannot distinguish a remaining source-width,
|
||||
optimizer-context, register, or scheduling cause. Park such a case as
|
||||
`unclassified` instead of inventing a specific mechanism. An unclassified
|
||||
park carries no code-generation recipe and grants no exact credit; its ledger
|
||||
must state the positive source evidence, the unresolved machine differences,
|
||||
and the evidence required to reopen it.
|
||||
|
||||
## Case catalog
|
||||
|
||||
| Case | Class | Evidence and source lever | Outcome / next action |
|
||||
|---|---|---|---|
|
||||
| `lra_new` (`f0e5a48`) | A | Reordering field initialization to the target's emitted store order aligned the failure block and lifecycle setup. | Exact; make store-order recovery a standard first pass. |
|
||||
| `object_new` (`claude/object-new-16`, then the isolated XDK scheduler-control lane) | A then D | Writing the cleanup as failure-first eliminated 10 relocation differences and two divergence regions. Only `fmuls` versus deferred `add esp, 0x18` ordering remained. A production-context reproducer then tested 20 one-factor legal-C controls; all forms that moved `fmuls` first also changed x87 dataflow or other bytes. | Preserve failure-first shape; park the dependency-free scheduler tie unless new source provenance identifies a distinct original expression. |
|
||||
| `hashtable_remove` (`f2d30b9`) | A | Source-oriented comparison order, reload points, and the shared deletion path aligned 496 padded bytes and 20 relocations. | Exact; use comparison polarity and reload timing before register tuning. |
|
||||
| `csstrcasecmp` (`e5852f8`, `claude/csstrcasecmp-15`) | A then C | `if (c1 != c2)` reproduces the target operand order; `if (c2 != c1)` does not. The remainder is an ESI/EDI parameter/local permutation. | Land only evidence-backed logic changes; handle the remaining mirror through a forced-register caller or park. |
|
||||
| terminal tab stops (`a917110`) | A | Identical six-byte data still failed because `static` produced storage class 3 while the target symbol was external, class 2. | Exact after external linkage/name recovery; audit symbol class, not just bytes. |
|
||||
| `generate_private_key` (`public_key_crypt.obj`) | A | Applying the exact `SWAP4` donor arithmetic to a local temporary selected the wrong accumulator form across hundreds of equivalent expression trees. Assigning the helper result to `private_key->dwords[i]` and applying `SWAP4` directly to that same member preserved frontend lvalue provenance and reproduced January exactly. | Exact without assembly, volatility, undefined behavior, or flag changes; preserve donor lvalue topology before classifying a commutative residual as a register tie. |
|
||||
| `objects.obj` BSS ownership | A/E | Explicit zero initialization plus declaration order recovered the linked 13-byte layout (`object_name_list@0`, `object_memory_pool@4`, `object_globals@8`, debug byte `@12`) without changing any exact function. January PDB/public-symbol and cross-TU-reference evidence proves the first three globals are source-private; csplit had defaulted their manually split labels to external because `symbols.json` omitted `"static": true`. | Keep the globals source-static and mark exactly those three csplit symbols static. Regenerate the split target and require exact size, offsets, storage classes, and whole-TU regression; do not paper over the difference with a semantic allowlist. |
|
||||
| `tif_packbits.obj` (`7c9c092`) | A | Target linkage, RCSID ownership, `_csmemcpy`, and disassembly-proven TIFF field offsets were required. Repository header layout differed from the target object. | Five functions and data exact; raw offsets are acceptable only with explicit target-layout evidence. |
|
||||
| random-math globals (`aef5a7c`) | A | Replacing an anonymous address placeholder with the real externally linked 20-byte globals structure fixed BSS ownership and relocation addends. | Exact functions retained; model globals explicitly before function tuning. |
|
||||
| `default_hash_function` (`f2d30b9`) | B | Target uses 16-bit product/partial-register code while natural C promotes the polynomial and key byte to 32 bits (80 target versus 64 candidate bytes). | Reopen only with a promotion/truncation lattice derived instruction by instruction. |
|
||||
| LRA verify/free/lock cluster (`f0e5a48`) | C | Seven functions share cache-in-EBX versus cache-in-EDI and private helper conventions. Isolated helper shaping did not move the joint allocation. | Anchor on callers with forced registers, then propagate; otherwise park the whole permutation together. |
|
||||
| hashtable probe helper `code_0010b270` (`073e794`) | C | Size, relocations, control flow, and operations agree; two return blocks mirror ECX and EDX. | Try return-materialization/single-exit shape once under the checklist, then park if unchanged. |
|
||||
| `reference_list_copy` lane | C | Target and candidate reduce to the same operations with a callee-saved register mirror after source-shape attempts. | Revisit only from its caller cluster and a hardware-forced anchor. |
|
||||
| `object_get_marker_by_name` lane | A | Recovering the direct object-header block access removed the artificial wrapper lifetime and reproduced the original call/dataflow structure. | Exact: 272 padded bytes, 11 relocations, and normalized SHA-256 `302db0f36677f304c6d076e0f16f3bb4e9603519b34d650a4311c296bd21c8cf`. |
|
||||
| `object_compute_node_matrices` (`claude/object-compute-node-matrices` plus the E2 closeout) | D | The corrected C now has the exact 6,560-byte padded size, `0xA44` frame, and 318 relocation identities. The first address drift is relocation 245: January homes `tag_get_name`'s EAX result to `[ebp-8]`, while VC7 keeps EAX live. Independent source, PDB, tail-diff, and legal-C shape audits found no controllable semantic or structural difference. | Park as an EAX-liveness/register-allocation tie. Reopen only if new local-variable provenance or a demonstrated legal-C compiler control appears. |
|
||||
| `data_decode_array` (`d0a735d`) | E | Padded bytes and 31 semantic relocations are exact; objdiff reports 85.19% because one target symbol plus addends corresponds to several rebuilt local labels. | Credited through the dynamic semantic ledger; no source work required. |
|
||||
| 37-function switch/local-label set (`24c998a`) | E | Full dual sweep found 37 real functions and 21,051 meaningful bytes exact under conservative COFF normalization but fuzzy under objdiff. | The allowlist is reverified on every progress run; uncertain or changed entries fail closed. |
|
||||
|
||||
## Complexity gate
|
||||
|
||||
For large aggregate objects such as `objects.obj`, queue a remaining function
|
||||
only when all of the following hold:
|
||||
|
||||
- padded size is below approximately `0x60`;
|
||||
- local state is small and unambiguous;
|
||||
- relocation count is low;
|
||||
- no large inlined helper or private-ABI cluster dominates the function.
|
||||
|
||||
Larger functions require a specific leverage reason (new structure proof,
|
||||
forced-register anchor, or reusable subsystem insight) before consuming an
|
||||
implementation lane.
|
||||
|
||||
## External type-information gate
|
||||
|
||||
For the supplied `h1_tags` executables, start with the
|
||||
[cross-build intake and missing-PDB identities](crossbuild_h1_tags_intake_20260906.md).
|
||||
The `_symbols.exe` images contain external PDB references, not complete
|
||||
embedded debug records. That ledger also records the IDA/Ghidra requirement
|
||||
and separates analysis-generated names from original-symbol evidence.
|
||||
|
||||
HCEX, Halo PC, October 2001, and community sources are hypothesis generators.
|
||||
Every imported field or enum value must carry a January-Xbox disassembly proof.
|
||||
Unproven spans remain named `reserved`/`unknown` and documented as such. No CEA
|
||||
offset enters a trusted header merely because it compiles or looks plausible.
|
||||
|
||||
## Original-bug policy
|
||||
|
||||
Exact builds preserve confirmed original behavior. Mark only defects supported
|
||||
by binary and layout evidence:
|
||||
|
||||
```c
|
||||
/* BUG (preserved for exact matching): <target behavior and evidence>.
|
||||
* A corrected build should <safe replacement>.
|
||||
*/
|
||||
```
|
||||
|
||||
Keep the safe fix disabled in the exact build. Do not label suspicious code as
|
||||
a bug without target-machine and structure-layout proof.
|
||||
@@ -1,113 +0,0 @@
|
||||
# objdiff v3.3.1 mis-scores MSVC data relocations
|
||||
|
||||
*2026-09-22, Lane C. Established independently three ways: by reading objdiff's
|
||||
source at tag v3.3.1, by black-box perturbation of January's own object files,
|
||||
and by auditing this project's own adjudication ledger. All three agree.*
|
||||
|
||||
## The defect
|
||||
|
||||
A data section's objdiff score is decided by its **relocations**. Two
|
||||
relocations are compared by `reloc_eq` in `objdiff-core/src/diff/data.rs`, which
|
||||
first tries `symbol_name_matches()`. That helper assumes a `$` in a symbol name
|
||||
is the Metrowerks `symbol$1234` unique-ID separator:
|
||||
|
||||
```rust
|
||||
if let Some((prefix, suffix)) = left_name.split_once('$') {
|
||||
if !suffix.chars().all(char::is_numeric) { return false; }
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Every MSVC mangled string literal contains `?$AA` — the encoded NUL. For example
|
||||
`??_C@_0P@LFOALBOL@objects_update?$AA@`. The suffix after the first `$` is
|
||||
`AA@`, which is not numeric, so **the helper returns false for two
|
||||
character-for-character identical names**.
|
||||
|
||||
`reloc_eq` then falls through to `address_eq`, which requires the target literal
|
||||
to sit at the same offset inside the *synthetic combined* `.rdata` that
|
||||
`report generate` builds (it forces `combine_data_sections: true`, and
|
||||
`do_combine_sections` concatenates every same-named section in COFF
|
||||
section-table order, padding each to `max(align, 4)`). csplit lists January's
|
||||
`.rdata` COMDATs in image order; CL emits ours in its own order. So the address
|
||||
test fails too, and a byte-perfect relocation is scored as a mismatch.
|
||||
|
||||
That costs the section twice. Relocated bytes are counted twice in
|
||||
`diff_data_symbol`
|
||||
|
||||
match_ratio = (bytes_ratio*len + relocs_ratio*reloc_bytes) / (len + reloc_bytes)
|
||||
|
||||
and, worse, the whole-section byte fallback in `diff_data_section` is gated
|
||||
behind `if all_left_relocs_match`, so it never runs. Since `report.rs` credits
|
||||
data all-or-nothing per section, one mis-compared relocation forfeits the
|
||||
entire section.
|
||||
|
||||
The code path is immune: `diff/code.rs::reloc_eq` compares names with plain `==`.
|
||||
|
||||
Fixed upstream in **objdiff v3.6.0** (2026-01-25), which added
|
||||
`get_normalized_symbol_name` in `obj/read.rs`; it returns `None` for
|
||||
`??_C@...?$AA@` so `symbol_name_matches` falls back to exact equality.
|
||||
|
||||
## Reproduction
|
||||
|
||||
Copy January's `objects.obj`, swap only the two `.rdata` COMDAT section headers
|
||||
for `_object_memory_release_procs` (24 B) and the `objects_update` literal
|
||||
(15 B), fixing symbol section numbers; change nothing else. January against
|
||||
itself scores `.data` 100.0; January against that header-swapped copy scores
|
||||
`.data` 99.739235 — the exact production number. Swapping two COFF *symbol
|
||||
table* entries instead leaves it at 100.0, so symbol-table order is inert.
|
||||
|
||||
## Scale, measured at HEAD
|
||||
|
||||
40 data sections / **32,262 bytes** have identical size, identical raw bytes and
|
||||
an identical relocation multiset, and would score exactly 100.000000 under an
|
||||
exact-name rule. Of those:
|
||||
|
||||
* **37 sections / 29,582 bytes are already credited** by
|
||||
`config/semantic_data_matches.json`. No progress bytes are being lost there —
|
||||
but they are credited as *adjudications*, and the standing rule is that
|
||||
adjudicated does not count as closed.
|
||||
* **3 sections / 2,680 bytes are genuinely uncredited**:
|
||||
`source/ai/actions .rdata` (2,388), `source/ai/ai_communication .data` (276),
|
||||
`source/ai/actions .data` (16).
|
||||
|
||||
## Recommendation
|
||||
|
||||
Upgrading the differ to >= v3.6.0 is the root-cause fix. It would recover the
|
||||
2,680 uncredited bytes and let roughly 37 adjudications be retired, converting
|
||||
29,582 bytes from adjudicated to genuinely exact. That is a shared build-tool
|
||||
change and needs an owner decision, and it must be measured board-wide first,
|
||||
because a differ upgrade re-scores everything.
|
||||
|
||||
Do **not** chase these sections with source edits. The only source-side lever is
|
||||
which `.rdata` COMDATs a TU emits and in what order, so that a literal lands at
|
||||
January's combined offset — and the target order is csplit's, i.e. the linked
|
||||
image's layout, which is a link-time property. Reordering or inventing literals
|
||||
to shift an offset fails the strip test.
|
||||
|
||||
Do **not** add new adjudications for them either; that papers over the
|
||||
instrument. Two entries were retired on 2026-09-22 for the opposite reason —
|
||||
`cheats .bss` and `tif_version .data` became genuine matches, so their
|
||||
adjudications were deleted at no cost to credited progress.
|
||||
|
||||
## Triage rule this establishes
|
||||
|
||||
Run the January-against-January self-diff **before** spending any wave on data,
|
||||
and **regenerate it whenever the differ changes**. Rewrite `objdiff.json` with
|
||||
`base_path = target_path` and absolute paths, drop `custom_make`/`build_target`,
|
||||
then `objdiff-cli report generate`; it takes 0.12 s over all 833 units.
|
||||
|
||||
Under v3.3.1 it capped 47 sections / 87,889 bytes. **Under v3.6.0 it caps
|
||||
nothing at all** - 0 sections, 0 bytes. Every one of those "permanent" ceilings
|
||||
was this same defect: a January-side string COMDAT comparing unequal to itself,
|
||||
so even a byte-identical copy could not reach 100. The campaign treated 87,889
|
||||
bytes as unreachable on the strength of a number produced by the broken
|
||||
comparator. Do not quote the old figure, and do not kill a target with a stale
|
||||
ceiling report.
|
||||
|
||||
## Resolution
|
||||
|
||||
Landed 2026-09-22: `sln.objdiff_tag` pinned to v3.6.0, and the 40 adjudications
|
||||
the fix makes redundant retired in the same commit. Board effect, measured on
|
||||
identical objects: raw data +34,886, raw code and functions unchanged, zero
|
||||
units losing anything, credited data +5,296, adjudications 43 -> 3. v3.8.1 was
|
||||
measured and rejected - same data gain, but it loses 6 bytes of code.
|
||||
@@ -1,91 +0,0 @@
|
||||
# Object exact-match strategy logs
|
||||
|
||||
For the completed/interrupted Opus 2 and new Fable 5 lanes, start with the
|
||||
[current reconciliation queue](../reconciliation_queue_20260907.md). It separates
|
||||
published progress, donor claims, dirty work, owner holds and tooling defects.
|
||||
|
||||
Every object that receives implementation or matching work must maintain one
|
||||
Markdown ledger in this directory. The filename is the object name with
|
||||
`_obj.md`, for example `players_obj.md`.
|
||||
|
||||
General techniques that apply across translation units belong in
|
||||
`docs/exact_match_acceleration_playbook.md`; object-specific measurements stay
|
||||
in the individual ledger.
|
||||
|
||||
Start constant and diagnostic recovery with the
|
||||
[common constants reference](../common_constants.md) and
|
||||
[shared assertion API](../assertions.md), before testing guessed literals.
|
||||
|
||||
The purpose is to make matching work cumulative. A new lane must be able to
|
||||
distinguish an untried evidence-backed source shape from a spelling that has
|
||||
already compiled to the same bytes.
|
||||
|
||||
## Required contents
|
||||
|
||||
Each ledger must include:
|
||||
|
||||
1. **Scope and provenance**
|
||||
- source translation unit and target object;
|
||||
- exact compiler identity and flags;
|
||||
- target-build provenance used for names, layouts, or source topology.
|
||||
2. **Validated baseline**
|
||||
- exact/total function count and padded code bytes;
|
||||
- exact/total data sections and bytes;
|
||||
- for every residual: target/base size, relocation count, normalized hash,
|
||||
and first meaningful divergence.
|
||||
3. **Accepted controls**
|
||||
- the source shapes retained in production;
|
||||
- why each shape is supported by binary or provenance evidence.
|
||||
4. **Experiment matrix**
|
||||
- every meaningful source shape tested;
|
||||
- resulting size, relocations, normalized hash, first divergence, and
|
||||
sibling-regression result;
|
||||
- whether it was retained or reverted.
|
||||
5. **Do-not-repeat list**
|
||||
- equivalent spellings or compiler-control attempts already exhausted;
|
||||
- unsafe or prohibited techniques.
|
||||
6. **Residual classification**
|
||||
- source/topology, ABI/register, scheduling, ownership/relocation, data, or
|
||||
unresolved;
|
||||
- clearly separate measured fact from inference.
|
||||
7. **Reopen criteria**
|
||||
- the exact new evidence that would justify spending another lane.
|
||||
8. **Disposition**
|
||||
- strict exact and eligible for `Matching`, still active, or rigorously
|
||||
parked;
|
||||
- never grant credit from a fuzzy percentage, equal size alone, or semantic
|
||||
plausibility.
|
||||
|
||||
## Lane rules
|
||||
|
||||
- Update the ledger after every bounded experiment batch, not only at handoff.
|
||||
- Rebuild with XDK 3911 and the repository flags after each retained change.
|
||||
- Gate every function and owned data section with the hardened comparator.
|
||||
- Run the whole-translation-unit regression sweep before committing.
|
||||
- Revert failed source shapes immediately.
|
||||
- Treat exact bytes as necessary but not sufficient: reject semantically
|
||||
nonsensical, historically implausible, logically meaningless, or inert
|
||||
compiler-steering source, even when it happens to match. Coincidental byte
|
||||
equality never authenticates the source. Park the best honest fuzzy
|
||||
reconstruction when a natural exact spelling is not available.
|
||||
- Do not use inline assembly outside a sparse, provenance-backed helper/math
|
||||
exception. Never use volatile byte forcing, undefined behavior, object-byte
|
||||
patches, or compiler-flag changes.
|
||||
- A parked residual must preserve enough evidence for another agent to
|
||||
reproduce the classification without redoing the full search.
|
||||
- Label a defect `BUG (original)` only when January binary/source evidence
|
||||
proves the defective behavior belongs to the original game. A mistake or
|
||||
omission in our reconstruction is not an original bug. Preserve proven
|
||||
original behavior in the matching build and document the corrected-build
|
||||
alternative in a comment without changing the matching token/line shape.
|
||||
- When retroactively documenting an old lane, state which experiment details
|
||||
were not preserved. Never manufacture source variants, hashes, or outcomes
|
||||
to make a historical matrix look complete.
|
||||
|
||||
## Minimal experiment row
|
||||
|
||||
```markdown
|
||||
| ID | Source shape | Size T/B | Relocs T/B | Base hash | First divergence | Siblings | Decision |
|
||||
|---|---|---:|---:|---|---|---|---|
|
||||
| E01 | ... | `0x.../0x...` | `N/N` | `...` | `+0x...: ...` | `K/K exact` | reverted |
|
||||
```
|
||||
@@ -1,113 +0,0 @@
|
||||
# action_alert.obj complete reconstruction and fuzzy closeout (2026-09-01)
|
||||
|
||||
## Result
|
||||
|
||||
`source/ai/action_alert.obj` advanced from five exact functions and seven
|
||||
unwritten functions to eleven exact functions and one complete, documented
|
||||
fuzzy residual. There are no unwritten functions left in the object.
|
||||
|
||||
The newly exact functions are:
|
||||
|
||||
- `action_alert_setup`
|
||||
- `action_alert_flush_position_indices`
|
||||
- `action_alert_flush_structure_indices`
|
||||
- `distance_squared3d`
|
||||
- `action_alert_update`
|
||||
- `action_alert_perform`
|
||||
|
||||
The remaining private function was recovered as
|
||||
`action_alert_next_position`; the address-derived symbol was removed from
|
||||
`config/symbols.json` and the symbol remains translation-unit private.
|
||||
|
||||
## Evidence and donor audit
|
||||
|
||||
The reconstruction was checked against all Action Alert ledgers, repository
|
||||
history, registered branches and worktrees, the January target disassembly and
|
||||
relocations, and the later HCEA semantic sources under:
|
||||
|
||||
`research-cache/halocea-full-blobs-20260830/src/blam/ai/action_alert_*.c`
|
||||
|
||||
Pastudan's setup/update reconstruction was also inspected. Marathon contains
|
||||
no direct Action Alert donor. No registered worktree contains a complete
|
||||
definition of either `action_alert_perform` or `action_alert_next_position`,
|
||||
and no farther candidate than the retained source was found.
|
||||
|
||||
The HCEA source and AI definitions corroborate the complete behavior:
|
||||
|
||||
- disabled/passenger, no-order, and no-encounter rejection;
|
||||
- encounter, squad, and move-position traversal;
|
||||
- current-position, actor-distance, noncombat-sequence, and nearby-prop
|
||||
availability tests;
|
||||
- cseries bit-vector tracking of unavailable positions;
|
||||
- weighted random selection and forward, ping-pong, and per-tick-random
|
||||
traversal;
|
||||
- dwell-time selection, animation startup, and move-position state updates.
|
||||
|
||||
Action Alert prototypes now live in the closest owner header, `actions.h`,
|
||||
rather than as ad hoc declarations in `actions.c`. Accesses use the project's
|
||||
typed actor, unit, definition, tag-block, and scenario helpers. The source
|
||||
uses semantic cseries types and enum constants and keeps explicit returns.
|
||||
|
||||
## Residual measurement
|
||||
|
||||
Focused gate after reconstruction:
|
||||
|
||||
```text
|
||||
residual 784 _action_alert_next_position [size 768!=784, sha]
|
||||
== exact 11 residual 1 unwritten 0 (of 12 listed)
|
||||
```
|
||||
|
||||
Fresh full campaign-report similarity for the residual is `99.46479%`.
|
||||
This value, rather than a separate aligned-disassembly score, is recorded in
|
||||
`config/parked.json`.
|
||||
|
||||
- Target: 784 padded bytes, 18 relocations, normalized SHA-256
|
||||
`677fd6cc1a9e66de32123c4614de5a0cc1188501baee69ea20fd5bf74eac3fe4`.
|
||||
- Candidate: 768 padded bytes, 18 relocations, normalized SHA-256
|
||||
`4e16c85b544ded3352df48ee7baa0e19b5a34a45e421a975cf11cd771184f371`.
|
||||
|
||||
Aligned instruction comparison is retained only as diagnostic evidence. It
|
||||
shows that the geometry, prop-iterator, bit-vector, random-selection, and
|
||||
ordered-traversal body is byte-identical. The remaining decoded differences
|
||||
are limited to January preloading the `NONE` result in EAX, the resulting
|
||||
AL/CL and EAX/ECX allocation choices in the entry guard, two equivalent
|
||||
full-EAX versus AX `NONE` returns, and target-envelope padding.
|
||||
|
||||
## Bounded source-shape audit
|
||||
|
||||
Ordinary-C probes covered combined, separate, and enclosing entry guards;
|
||||
short and long default-result lifetimes; declaration order; direct and
|
||||
assigned random returns; natural `for` and `while` traversal; and switch
|
||||
default/case arrangements. The retained `while` traversal reproduces
|
||||
January's initialization schedule, and initializing the traversal direction
|
||||
before a semantic enum switch with no redundant default reproduces January's
|
||||
entire switch body. The remaining entry/result variants either returned to
|
||||
the same compiler fixed point or disturbed larger exact regions.
|
||||
|
||||
No volatile or register forcing, compiler barrier, pragma, inline assembly,
|
||||
fake dependency, raw structure offset, undefined behavior, forced inlining,
|
||||
or nonsensical control flow is retained. The function is parked as
|
||||
`register-allocation` and should reopen only for authoritative January source
|
||||
or local-variable records, or a natural compatible-compiler donor that
|
||||
explains the default-result lifetime.
|
||||
|
||||
## Validation
|
||||
|
||||
The admission run passed:
|
||||
|
||||
- full `ninja`, including report, semantic report, and progress validation;
|
||||
- an independent strict per-function sweep against a clean build of base
|
||||
`f73b19d30`: 5,026 exact to 5,032 exact, exactly the six Action Alert gains
|
||||
above, with zero lost functions and zero unit-read errors;
|
||||
- focused gates: Action Alert `11/12` exact with one parked residual, Actions
|
||||
`58/63` exact with its five pre-existing parks, Units `189/189`, objects
|
||||
`121/121`, and object types `31/31`;
|
||||
- `python -m tools.parked_functions`: 78 active, zero stale, zero invalid;
|
||||
- `python -m pytest -q`: 255 passed;
|
||||
- semantic audit: 5,032 strict exact functions, 134 hidden exact
|
||||
functions, and zero unit errors;
|
||||
- fake-match scan of all changed C/header files: zero findings;
|
||||
- object-admission audit: no contradictions or revocations (one unrelated
|
||||
pre-existing `player_rumble` ownership-review candidate);
|
||||
- all-unit `point_from_line3d` owner comparison against the base: no new or
|
||||
lost COMDAT owner.
|
||||
-152
@@ -1,152 +0,0 @@
|
||||
# `action_alert.obj`: `distance_squared3d` wrapper fixed point (2026-08-26)
|
||||
|
||||
## Outcome
|
||||
|
||||
No production source change and no matching credit. One evidence-backed
|
||||
candidate disproved the locally renamed inline-wrapper topology for
|
||||
`_distance_squared3d`: the candidate emitted 48 padded bytes, while January
|
||||
and every exact donor emit 64. The source was immediately reverted without a
|
||||
tuning compile, the committed five-function baseline was rebuilt, and its
|
||||
whole-TU manifest is green.
|
||||
|
||||
`action_alert.obj` therefore remains 5/12 exact functions and 177/2,120
|
||||
meaningful code bytes. The retained production commits remain:
|
||||
|
||||
- `020449c3b3518fd6bbc1dfbe739ab3a15762befa`
|
||||
(`Match action alert geometry wrappers`);
|
||||
- `5196b8e4b409c571abc6be5634d0d09bc90ac9e5`
|
||||
(`Record action alert geometry validation`).
|
||||
|
||||
## Frozen target and baseline
|
||||
|
||||
The clean committed translation unit was frozen at `5196b8e4` in:
|
||||
|
||||
- `build/audit/action_alert_distance_squared_baseline_20260826.json`;
|
||||
- manifest SHA-256
|
||||
`f1ceaca1e7bd5c97bbac65192214909d4068cb9532af1f0cd29973938a3ec30c`.
|
||||
|
||||
The January target is:
|
||||
|
||||
- 49 meaningful / 64 padded bytes;
|
||||
- zero relocations;
|
||||
- normalized SHA-256
|
||||
`f42fa39f289bfa50174aa61e77b345b092df8329d46f43f88ca127227ad1e9c8`;
|
||||
- split-object SHA-256
|
||||
`bb7a70aae881cdf5672ae48c3b9c5b7d0cdcc9a30a90730672f04b71fa1cab5f`.
|
||||
|
||||
The baseline source SHA-256 is
|
||||
`0682c4b9fbf896d8434a1a8f6f78b355c2fabf20669601be3d25f64541fee93b`
|
||||
and its Git blob is `8de8debb9ac7108acc7352c53e36e305f75d06f7`.
|
||||
|
||||
## Same-name donor census
|
||||
|
||||
The canonical nested body is owned by `source/math/real_math.h`:
|
||||
|
||||
```c
|
||||
__inline real distance_squared3d(
|
||||
real_point3d const *a,
|
||||
real_point3d const *b)
|
||||
{
|
||||
real_vector3d v;
|
||||
return magnitude_squared3d(vector_from_points3d(a, b, &v));
|
||||
}
|
||||
```
|
||||
|
||||
The read-only census script
|
||||
`build/audit/find_action_alert_distance_donors_20260826.py` has SHA-256
|
||||
`c8989f86e767ca76965766eace71c8f8a9d326d96b32545df14e219fd3a32e72`.
|
||||
It found twelve rebuilt objects defining the same-name section, and hardened
|
||||
comparison reports every one `all_equal: true` against the action-alert
|
||||
target:
|
||||
|
||||
- `source/ai/action_fight.obj`;
|
||||
- `source/ai/action_guard.obj`;
|
||||
- `source/ai/action_search.obj`;
|
||||
- `source/ai/action_uncover.obj`;
|
||||
- `source/ai/actor_perception.obj`;
|
||||
- `source/effects/material_effects.obj`;
|
||||
- `source/game/game_engine.obj`;
|
||||
- `source/objects/objects.obj`;
|
||||
- `source/physics/breakable_surfaces.obj`;
|
||||
- `source/physics/collisions.obj`;
|
||||
- `source/physics/physics.obj`;
|
||||
- `source/units/units.obj`.
|
||||
|
||||
Direct hardened comparisons against both `action_fight.obj` and `units.obj`
|
||||
independently prove the 64 padded bytes and zero-relocation inventory. The
|
||||
donors obtain the COMDAT from a real call to the canonical header inline;
|
||||
none supplies an ordinary out-of-line source definition that can be
|
||||
transplanted verbatim.
|
||||
|
||||
## Sole candidate and rejection
|
||||
|
||||
The candidate locally renamed `distance_squared3d` across the header include
|
||||
and added the ordinary wrapper:
|
||||
|
||||
```c
|
||||
real distance_squared3d(
|
||||
real_point3d const *a,
|
||||
real_point3d const *b)
|
||||
{
|
||||
return distance_squared3d_inline(a, b);
|
||||
}
|
||||
```
|
||||
|
||||
This is ordinary C89 and obeys all formatting and return rules. Exactly one
|
||||
normal VC7 compile was spent. The preserved first candidate is:
|
||||
|
||||
- `build/audit/action_alert_distance_squared_first_current_tu_20260826.obj`;
|
||||
- raw SHA-256
|
||||
`c20dfa1ae881e1fae04d85b0a1f8e8911c837ece78b17bc33f64bcac6d5734c6`.
|
||||
|
||||
Its `_distance_squared3d` section is:
|
||||
|
||||
- 48 padded bytes;
|
||||
- zero relocations;
|
||||
- normalized SHA-256
|
||||
`3e3811d46757035eda49d4b9374d60a716646e589c018726d37a8e0ae2e3564a`.
|
||||
|
||||
The wrapper therefore changes the compilation context enough for VC7 to
|
||||
collapse the canonical nested operation into a shorter form. It is not the
|
||||
same emission topology as the donor COMDAT. The candidate whole-TU gate also
|
||||
fails closed on the additive symbol/debug inventory and records
|
||||
`_distance_squared3d` in `changed_nonexact`. Direct comparison proves the five
|
||||
accepted bodies themselves remained byte-exact, but the manifest failure is
|
||||
independently sufficient to reject the candidate.
|
||||
|
||||
No second spelling, hand expansion, compiler option, object permutation,
|
||||
allowlist, adjudication, exception, synthetic caller, or byte-forcing form was
|
||||
compiled.
|
||||
|
||||
## Restoration
|
||||
|
||||
The candidate source was removed with `apply_patch`, returning
|
||||
`source/ai/action_alert.c` byte-for-byte to the committed blob. The generated
|
||||
object path was resolved inside the authoritative worktree, that single object
|
||||
was deleted, and one restoration build was run. Its nondeterministic raw
|
||||
SHA-256 is
|
||||
`28105c5cf2ead523cf5e98dfb87afb09330164d4e5cb233f3c776167345f92b3`.
|
||||
|
||||
The frozen manifest then reports:
|
||||
|
||||
- `ok: true`;
|
||||
- no failures or warnings;
|
||||
- `changed_nonexact: []`;
|
||||
- `_action_alert_begin`, `_action_alert_control`,
|
||||
`_vector_from_points3d`, `_magnitude_squared3d`, and
|
||||
`_real_random_range` all `still_exact`.
|
||||
|
||||
Direct hardened comparison of the same five functions remains
|
||||
`all_equal: true`. No protected path changed, no tracked path was deleted,
|
||||
and nothing was pushed.
|
||||
|
||||
## Reopen criterion
|
||||
|
||||
Do not retry the renamed-inline wrapper. Reopen `_distance_squared3d` only
|
||||
with genuinely new evidence that reproduces the donor COMDAT emission context
|
||||
without a synthetic caller—for example an authenticated ordinary definition,
|
||||
a grounded VC7 inline/COMDAT topology explanation, or another natural
|
||||
translation-unit use that makes the canonical header definition emit under
|
||||
the function's real ownership. A direct ordinary copy of the canonical body
|
||||
is a distinct unmeasured hypothesis, but it is not justified for another
|
||||
production compile merely by the failed wrapper result.
|
||||
@@ -1,124 +0,0 @@
|
||||
# `action_alert.obj` Jonas prefix recovery
|
||||
|
||||
This Jonas/Codex ledger records a bounded, fail-closed recovery of the five
|
||||
requested prefix bodies in `source/ai/action_alert.obj`. Only
|
||||
`_action_alert_control` was independently strict on the first natural
|
||||
candidate, so it alone is retained. The object advances from 2/12 to 3/12
|
||||
exact functions and remains `NonMatching`; no data or whole-object credit is
|
||||
claimed.
|
||||
|
||||
## Scope and provenance
|
||||
|
||||
- Authoritative integration base:
|
||||
`7d2ff479dde012f94cc08857e4cc74650b85b9af`.
|
||||
- Baseline `action_alert.c` blob:
|
||||
`45f0eae365e5f6e087507143bd68549c676ab736`.
|
||||
- Retained `action_alert.c` blob:
|
||||
`01c9af4f179f4fc7e3792413c7a18cf3d7899c5a`.
|
||||
- Retained source SHA-256:
|
||||
`d10627b7393f20bd86037df3da279333b2c0e99c0a7adb24d77320e5865d5865`.
|
||||
- January executable SHA-256:
|
||||
`4cc87b45f721270392a96f1674ed2b5cd4a7bb4355faeab4531d1cf1884d9520`.
|
||||
- January split-object SHA-256:
|
||||
`bb7a70aae881cdf5672ae48c3b9c5b7d0cdcc9a30a90730672f04b71fa1cab5f`.
|
||||
- The raw candidate-object hash is deliberately omitted because the XDK COFF
|
||||
container timestamp changes across forced builds. The normalized function
|
||||
hashes below are the reproducible admission identities.
|
||||
- Clean HCEA semantic donor commit:
|
||||
`c168af2e747d3095d9a29418ae401f3a39544863`. The screened source blobs
|
||||
are `a8494315eb9fbbc0b57fe9ae169b76f5203044fe` (setup),
|
||||
`bdc904682c5a2ba16a90f308cfeef79c97be2a68` (control),
|
||||
`16f1703d50e1daa0b8f9fa15a6d5aad76c3a484d` (flush position),
|
||||
`3018bec7791130ca7a11f95f320d0c05cf257f81` (flush structure), and
|
||||
`c4f463bf4613fc0240debabaa8ad40cc494eb252` (update).
|
||||
|
||||
HCEA supplies semantic names and natural control-flow evidence. The January
|
||||
COFF remains the sole authority for bytes, padding, relocations, and symbolic
|
||||
destinations.
|
||||
|
||||
## One-shot strict result
|
||||
|
||||
The five requested bodies were compiled together once with the repository's
|
||||
natural XDK 3911 command. Each body was compared independently with the
|
||||
hardened COFF comparator. The four nonexact bodies were then removed without
|
||||
another source-shape experiment or any code-generation tuning. The later full
|
||||
build and forced regression are validation replays of this fail-closed final
|
||||
source.
|
||||
|
||||
| Function | Target meaningful | Target padded | Relocations | Target normalized SHA-256 | First candidate result |
|
||||
| --- | ---: | ---: | ---: | --- | --- |
|
||||
| `_action_alert_setup` | 126 | 128 | 7 | `225015f380c74c1a19d563730b7820375cd37490eb40cb6d67e3404bc46c9cc0` | rejected: 144 padded, 7 relocations, SHA `47b3dc2358c61240e9d48276b9d00caf88d8384cfc505e764f2929cf32ba7491` |
|
||||
| `_action_alert_control` | 73 | 80 | 3 | `8be5d8f243b76cbf9dd2c4f7f35b4509c349bc970a9b2fc1518a71e3e6a1fbb3` | **retained: strict exact** |
|
||||
| `_action_alert_flush_position_indices` | 40 | 48 | 2 | `02db3d8b0b933d6e26b970c3c7a3639e7005e78304692915295d835f61eff579` | rejected: 48 padded, 2 relocations, SHA `90abe46d68627d1a83f1a5a89d4d7ecd6d86b0ee14b514917b19c73f96d17335` |
|
||||
| `_action_alert_flush_structure_indices` | 39 | 48 | 2 | `1b6fb9035cd64ac3bd1a66e1be208f3dc09ea95d32ef17f960e5bd960540a466` | rejected: 48 padded, 2 relocations, SHA `75fef43de1d32d255e61481ac5402bab1d683f3c801fb2a252438d8ba603434d` |
|
||||
| `_action_alert_update` | 323 | 336 | 13 | `0b4be7a9c0704dc3075a31fabf85a1f5ab7868be9d5fc3676685252d0aeaaa43` | rejected: 336 padded, 13 relocations, SHA `13ed6e0ef99086fe5eb49463dfa54e086057c8155982114cd78ea8e212608dea` |
|
||||
|
||||
The retained control body is exact in padded size, every normalized byte, and
|
||||
all three relocation addresses, types, destinations, and addends. It uses the
|
||||
established typed `actor_get` and `actor_definition_get` accessors, sets the
|
||||
January-proven noncombat idle-look value `1`, tests the named actor-definition
|
||||
bit 6, and sets both crouch Booleans when that bit is active.
|
||||
|
||||
The wave adds 73 meaningful and 80 padded exact code bytes. Together with the
|
||||
pre-existing exact `_action_alert_begin` and `_real_random_range`, the final
|
||||
object measures 3/12 exact functions, 101/2,120 meaningful code bytes, and
|
||||
128/2,240 padded code bytes. The preserved functions were replayed directly:
|
||||
|
||||
| Preserved function | Meaningful | Padded | Relocations | Normalized SHA-256 |
|
||||
| --- | ---: | ---: | ---: | --- |
|
||||
| `_action_alert_begin` | 1 | 16 | 0 | `499f1f307c1cb989f968a6b7fcaec591e1828877223d0b0e7e8e8b76cde8c9ca` |
|
||||
| `_real_random_range` | 27 | 32 | 2 | `7ed2e50e8e1a701a98fcceeb6a6b67e05d997f21bdb9ff5ee2e848fd1a8f409a` |
|
||||
|
||||
## Fail-closed omissions and policy boundary
|
||||
|
||||
The setup, both flushes, and update definitions are absent from the final
|
||||
candidate. The two large target-only bodies `_code_00000950` and
|
||||
`_action_alert_perform` were never added or compiled in the candidate lane.
|
||||
The rejected update's temporary local 0x3C animation-reference view and its
|
||||
scenario, object, and unit includes were removed with the body. No shared
|
||||
header, tag-definition storage, configuration, semantic exception, parked
|
||||
record, or completion label changes.
|
||||
|
||||
The retained source is readable typed C with vertically formatted parameters
|
||||
and an explicit terminal `return;`. It contains no assembly, raw object-header
|
||||
access, pointer or union pun, inactive-union access, integer-address
|
||||
reconstruction, volatile scheduling device, force-inline annotation,
|
||||
optimizer pragma or barrier, synthetic anchor, byte-forcing expression, or
|
||||
undefined-behavior match.
|
||||
|
||||
The target owns 80 ordinary non-code bytes; the final candidate owns none and
|
||||
receives zero data credit. The existing exact begin and random-range bodies
|
||||
are textually unchanged.
|
||||
|
||||
## Validation
|
||||
|
||||
- Complete `halobetacache_build` and `libcmt_build`: pass.
|
||||
- Direct hardened comparison: retained control plus both preserved functions
|
||||
pass with exact normalized bytes and relocations.
|
||||
- Semantic audit: 470 units, 3,995 functions evaluated, 3,855 semantic exact,
|
||||
101 hidden exact, 36 ordinary-only, 3,916 accepted exact, and zero unit
|
||||
errors.
|
||||
- Campaign progress: 375/833 complete objects, 3,903/11,060 exact functions,
|
||||
472,316/2,198,102 exact code bytes, and 1,835,088/4,176,062 matched data
|
||||
bytes.
|
||||
- Halo progress: 273/468 complete objects, 3,736/7,574 exact functions,
|
||||
459,402/1,770,166 exact code bytes, and 1,829,896/3,923,451 matched data
|
||||
bytes.
|
||||
- Object-admission audit: zero candidates and zero revocations; only the
|
||||
inherited `source/shell/shell_xbox` completion-label contradiction remains.
|
||||
- Parked-function audit: three active, zero stale, and zero invalid entries.
|
||||
- Complete tooling suite: 179/179 tests pass.
|
||||
- Clean committed-state forced single-unit regression snapshot/check: all
|
||||
three accepted functions remain exact, with no failure or ownership change.
|
||||
- `git diff --check`, deleted-path, policy-token, and frozen-scope audits:
|
||||
pass.
|
||||
|
||||
The five frozen large-object sources are byte-identical to the integration
|
||||
base: `vehicles.c` (`4a01dc7c54717e1b063a0cac72b0178b4bb2bf04`),
|
||||
`ai_debug.c` (`517731845431f1e240b06742ab9ddfbf6e67e929`),
|
||||
`ai_script.c` (`c3c858af2e4d6bf1df6dccf013b9ba6ee09f332d`),
|
||||
`actions.c` (`b594c1d52afe683e3fc794be08bf40e2b7045e26`), and
|
||||
`units.c` (`19a15c4a3a47849ffd8ba0c13989c0c389452519`).
|
||||
Only `source/ai/action_alert.c` and this new Jonas ledger are tracked changes.
|
||||
No tracked file is deleted, no object is marked complete, and nothing is
|
||||
pushed.
|
||||
@@ -1,212 +0,0 @@
|
||||
# `action_alert.obj`: safe geometry pair (2026-08-26)
|
||||
|
||||
## Outcome
|
||||
|
||||
Two ordinary geometry helpers are newly strict-exact:
|
||||
|
||||
- `_vector_from_points3d`;
|
||||
- `_magnitude_squared3d`.
|
||||
|
||||
The wave adds two exact functions and 76 meaningful code bytes.
|
||||
`action_alert.obj` advances from 3/12 to 5/12 exact functions and from 101
|
||||
to 177 matched meaningful code bytes. It remains incomplete; no completion
|
||||
label, semantic exception, adjudication, data credit, or comparator waiver was
|
||||
added.
|
||||
|
||||
Source commit:
|
||||
|
||||
- `020449c3b3518fd6bbc1dfbe739ab3a15762befa`
|
||||
(`Match action alert geometry wrappers`).
|
||||
|
||||
## Frozen evidence
|
||||
|
||||
The untouched translation unit was frozen at commit
|
||||
`fe2e8631136da957ce6fe286fde456a480cbc2ba` in:
|
||||
|
||||
- `build/audit/action_alert_safe_geometry_pair_baseline_20260826.json`;
|
||||
- manifest SHA-256
|
||||
`769e1bda19900e12f7c3622d1e4f6632debc1ef84b5fcc6fe42ca72ce10c089d`.
|
||||
|
||||
The target functions have these authenticated January fingerprints:
|
||||
|
||||
| Function | Meaningful / padded bytes | Relocations | Normalized SHA-256 |
|
||||
| --- | ---: | ---: | --- |
|
||||
| `_vector_from_points3d` | 38 / 48 | 0 | `905f56dbe4597d2bacc201456ffc33464b166e0b6392dda24a1a3e109b637aa2` |
|
||||
| `_magnitude_squared3d` | 38 / 48 | 0 | `0d04579096eeab3a1c45f87774e1eb20ce4856dbac219f624a855e8c9ae99725` |
|
||||
|
||||
The canonical bodies and ABIs are fixed by `source/math/real_math.h`.
|
||||
Direct comparison against the exact same-name definitions in
|
||||
`build/base/source/math/real_math.obj` proves all 48 padded bytes of each
|
||||
function. The repository-wide same-name census also found 25 exact donors for
|
||||
`_vector_from_points3d` and 33 for `_magnitude_squared3d`. Both target
|
||||
sections have zero relocations, so there is no unresolved callee, owner, or
|
||||
addend hypothesis. This is a same-name, same-ABI transfer rather than a
|
||||
masked-shape guess.
|
||||
|
||||
`_distance_squared3d` was deliberately excluded. Its target section is 49
|
||||
meaningful / 64 padded bytes with zero relocations and normalized SHA-256
|
||||
`f42fa39f289bfa50174aa61e77b345b092df8329d46f43f88ca127227ad1e9c8`,
|
||||
but its canonical source nests another helper. That makes definition order and
|
||||
inline topology a separate evidence question; it was not bundled into this
|
||||
independent two-function wave.
|
||||
|
||||
## Claude documentation and tooling audit
|
||||
|
||||
All locally reachable Claude records that name this object or the applicable
|
||||
matching tools were reconciled before candidate selection.
|
||||
|
||||
- The Claude residual census at
|
||||
`C:/halo-worktrees/claude-near-complete-objects-20260816/research/residual_frontier.json`
|
||||
lists the three geometry functions only as January `target_only` sections.
|
||||
It records no candidate, residual measurement, source experiment, or fixed
|
||||
point for the selected pair. The file SHA-256 is
|
||||
`db87717092d2e7c71160619e9df25f0b940f1762725c81f8bd2d6ece77fbde0d`.
|
||||
- No reachable `claude/*` branch changes `source/ai/action_alert.c`. The
|
||||
current history contains the prior Jonas/Codex prefix, control, and random
|
||||
range recovery only.
|
||||
- The Claude copies of `docs/matching_methodology.md` and
|
||||
`docs/shape_transfer_executor_strategy.md` are byte-identical across the
|
||||
near-complete, finish-hs, and untried worktrees and to the current files.
|
||||
Their SHA-256 values are respectively
|
||||
`3eb52f6b2df7b94b4d732161c0f86e2becebbcf0b546824deb957882118b1b5c`
|
||||
and
|
||||
`072ee7b2b3a2900e401bec7f69bff475f57639456d9c6270d2ea51189aaefa83`.
|
||||
- Claude's `docs/house_rules.md`, SHA-256
|
||||
`9294b81dc2e1c92d75ffd2f9f289287131bdba3564ba95bb054b08189781bfe1`,
|
||||
requires ordinary C, canonical vector expressions, and evidence before a
|
||||
compile. The retained component expressions are the canonical header forms
|
||||
and are corroborated by exact same-name donors.
|
||||
- Claude's flag-provenance census confirms this TU uses the normal
|
||||
`/O2 /Oy- /DDEBUG /Dxbox` profile and contradicts `/QIfist` as a whole-TU
|
||||
alternative. No flag change was considered or used.
|
||||
- The Claude campaign README identifies
|
||||
`tools/coff_compare.section_infos_equal` as the acceptance gate. The
|
||||
current hardened comparator and whole-TU regression manifest were used
|
||||
directly; no in-memory edit harness, alias adjudication, or comparator
|
||||
exception was used.
|
||||
|
||||
The earlier local record
|
||||
`docs/object_matching_logs/action_alert_obj_jonas_prefix_recovery.md` was also
|
||||
read in full. Its one-shot covered setup, control, the two flush helpers, and
|
||||
update; only control survived. It did not compile or measure either helper in
|
||||
this wave, so no fixed point was reopened.
|
||||
|
||||
## Candidate discipline
|
||||
|
||||
The two inline identifiers are locally macro-renamed across the include block,
|
||||
then ordinary out-of-line definitions are appended after the already accepted
|
||||
random-range wrapper. `action_alert.c` has an empty private-code tail, so the
|
||||
append preserves every existing function section index. The macros only avoid
|
||||
duplicate C definitions; they do not alter optimization, calling convention,
|
||||
or emitted instructions.
|
||||
|
||||
The one normal VC7 candidate compile was strict-exact for both functions on
|
||||
the first attempt. There was no object permutation, compiler-flag change,
|
||||
allowlist, adjudication, comparator exception, object patch, intrinsic,
|
||||
alignment directive, synthetic anchor, or byte-forcing expression.
|
||||
|
||||
The preserved first candidate is:
|
||||
|
||||
- `build/audit/action_alert_safe_geometry_pair_first_current_tu_20260826.obj`;
|
||||
- raw SHA-256
|
||||
`76977841b7e1bac6c02bf3ca86ca56785c5d47a6f3d55bda7019847d270e0ad4`.
|
||||
|
||||
## Exact comparison and frozen gate
|
||||
|
||||
The hardened comparator reports `all_equal: true` for both additions and all
|
||||
three previously accepted functions:
|
||||
|
||||
- `_vector_from_points3d`;
|
||||
- `_magnitude_squared3d`;
|
||||
- `_action_alert_begin`;
|
||||
- `_action_alert_control`;
|
||||
- `_real_random_range`.
|
||||
|
||||
The frozen gate reports exactly the pair as `newly_exact`, all three inherited
|
||||
functions as `still_exact`, and `changed_nonexact: []`. Its sole hard finding
|
||||
is the expected additive symbol inventory from defining the two functions.
|
||||
|
||||
## Clean committed state and replay
|
||||
|
||||
The clean committed manifest is:
|
||||
|
||||
- `build/audit/action_alert_safe_geometry_pair_committed_20260826.json`;
|
||||
- commit `020449c3b3518fd6bbc1dfbe739ab3a15762befa`;
|
||||
- SHA-256
|
||||
`940551915655b88e2affb548bb9e62d687ec109d672b4d02dde0a79cd85af98f`.
|
||||
|
||||
Its post-rebuild check returns `ok: true`, no failures, no warnings, no
|
||||
changed nonexact functions, and all five functions above as `still_exact`.
|
||||
|
||||
The generated object path was resolved inside this worktree. That single file
|
||||
was deleted and rebuilt once from the committed source. Raw base-object hashes
|
||||
were:
|
||||
|
||||
- before replay:
|
||||
`76977841b7e1bac6c02bf3ca86ca56785c5d47a6f3d55bda7019847d270e0ad4`;
|
||||
- after replay:
|
||||
`c7646f7851aa760a7de32c2b52f9b391137eae2ede49cb028cb74740e9810acb`.
|
||||
|
||||
VC7 debug/build records are nondeterministic, so raw object hashes are not the
|
||||
equality oracle. The post-replay manifest is green and direct hardened
|
||||
comparison remains `all_equal: true`.
|
||||
|
||||
Pinned artifacts:
|
||||
|
||||
- target split object:
|
||||
`bb7a70aae881cdf5672ae48c3b9c5b7d0cdcc9a30a90730672f04b71fa1cab5f`;
|
||||
- source file before/after:
|
||||
`84e4f2c3591554c6d34dc0701173bbfb11fb137ff4053a571cf3a55041d252ad` /
|
||||
`0682c4b9fbf896d8434a1a8f6f78b355c2fabf20669601be3d25f64541fee93b`;
|
||||
- source blob before/after:
|
||||
`01c9af4f179f4fc7e3792413c7a18cf3d7899c5a` /
|
||||
`8de8debb9ac7108acc7352c53e36e305f75d06f7`;
|
||||
- canonical report:
|
||||
`932d130576c91043f603dec2712ad9afb5dc9bfc98a1d5a991af3ebf482ca4f6`;
|
||||
- semantic report:
|
||||
`33c07f434de44fc536e8ba0ddbf98b3d4eb0b9056fe243e84dceed5ec6721bde`;
|
||||
- VC7 compiler:
|
||||
`483e00c47bb08d699475a642bcff15b5b2036350b31c540e88a506baf101da11`;
|
||||
- hardened comparator:
|
||||
`411e41698a9491a7b69430307d03f844ee3144633e5d3038d3ffde81a8eccfb7`;
|
||||
- regression gate:
|
||||
`d09b46dd2331ff7ca677cad78a66c780c4effa41a5389f0c614c9760d7632a5f`.
|
||||
|
||||
Supporting audits:
|
||||
|
||||
- admission SHA-256:
|
||||
`f0aa45c22cc604fb74abc388b06dd79a27e7a0b498a5d28837a9e785680c9a36`;
|
||||
- parked-frontier SHA-256:
|
||||
`cfac03aea5be607c19a6a40bcdbc1164e71ffb0179602af4bd37b3fd50e26d1d`.
|
||||
|
||||
## Canonical progress and gates
|
||||
|
||||
After regeneration:
|
||||
|
||||
- canonical code: 508,806/2,198,102 bytes and 4,215/11,060 functions;
|
||||
- complete files: 377/833;
|
||||
- Halo category: 495,892/1,770,166 code bytes and 4,048/7,574 functions;
|
||||
- Halo complete files: 275/468;
|
||||
- semantic audit: 470 units and 4,323 functions evaluated, 4,180 semantic
|
||||
exact, 114 hidden-exact functions / 64,705 hidden bytes, 4,241 accepted
|
||||
exact, and zero unit errors.
|
||||
|
||||
Repository gates:
|
||||
|
||||
- object admission: zero candidates and zero revocations; only the inherited
|
||||
`shell_xbox` completion-label contradiction remains;
|
||||
- parked validation: three active, zero stale, zero invalid;
|
||||
- tooling tests: 179/179 pass;
|
||||
- Halo and libcmt dry graphs: no work;
|
||||
- protected-path touches: zero;
|
||||
- deleted tracked paths: zero;
|
||||
- no push.
|
||||
|
||||
## House-rule audit
|
||||
|
||||
Every parameter is on its own line and both functions end with explicit value
|
||||
returns. The retained source is C89. It contains no assembly, `register`,
|
||||
`volatile`, barrier, pragma, explicit intrinsic, attribute, raw address,
|
||||
pointer/integer reconstruction, pointer or union pun, undefined behavior,
|
||||
synthetic anchor, or byte-forcing form. These functions perform no tag or
|
||||
object access, so the typed-access rules are not implicated.
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
# `action_alert.obj`: setup store-order one-shot rejection (2026-08-30)
|
||||
|
||||
## Scope and result
|
||||
|
||||
This lane tested one independently sourced ordinary-C shape for
|
||||
`_action_alert_setup` and no other residual owner. The candidate was rejected
|
||||
after its first compile. The source was restored immediately; the object
|
||||
remains **5/12 exact** and **224/2240 padded bytes exact**.
|
||||
|
||||
The five inherited exact owners were rechecked after restoration:
|
||||
|
||||
- `_action_alert_begin`
|
||||
- `_action_alert_control`
|
||||
- `_vector_from_points3d`
|
||||
- `_magnitude_squared3d`
|
||||
- `_real_random_range`
|
||||
|
||||
## New premise
|
||||
|
||||
The fresh premise came from the readable Pastudan history at commit
|
||||
`1146f5b799111ab72f2f5e37303a4c050945b88b`, file
|
||||
`src/halo/math/vector_math.c` (the action-alert implementation around lines
|
||||
368-388 in that snapshot). Unlike the previously tested HCEA-derived shape,
|
||||
it preserves the January target's post-`csmemset` field-store order:
|
||||
|
||||
1. conditional `move_position_order`
|
||||
2. `target_move_position_index = NONE`
|
||||
3. `pending_move_position_index = initial_move_position_index`
|
||||
4. `move_position_increasing = TRUE`
|
||||
5. `wait_ticks = 0`
|
||||
6. `must_play_animation = FALSE`
|
||||
|
||||
The canonical declaration was retained unchanged:
|
||||
|
||||
```c
|
||||
boolean action_alert_setup(
|
||||
long actor_index,
|
||||
short move_position_order,
|
||||
long initial_move_position_index,
|
||||
struct alert_state_data *state_data);
|
||||
```
|
||||
|
||||
This was deliberately only a store-order adoption, not the complete Pastudan
|
||||
lift. The Pastudan snapshot's recovered formal sequence at line 372 is
|
||||
`int actor_handle, int value, short field, void *state`: its second argument is
|
||||
full width and its third is narrow. This lane retained the canonical
|
||||
`long, short, long, pointer` declaration rather than changing a cross-TU ABI
|
||||
as part of the source-shape test.
|
||||
|
||||
The body used typed fields, `actor_get`, the line-35 `state_data` assertion,
|
||||
`csmemset(state_data, 0, sizeof(*state_data))`, and the store sequence above.
|
||||
It used no inline assembly, `volatile`, `register`, pragmas, raw structure
|
||||
offsets, type punning, or byte-forcing constructs.
|
||||
|
||||
## Strict comparison
|
||||
|
||||
Only `build/base/source/ai/action_alert.obj` was scheduled; the Ninja dry run
|
||||
showed exactly one `CL` edge. The first and only candidate compile produced:
|
||||
|
||||
| Measurement | January target | Candidate |
|
||||
|---|---:|---:|
|
||||
| Padded section size | 128 | 128 |
|
||||
| Relocations | 7 | 7 |
|
||||
| Normalized SHA-256 | `225015f380c74c1a19d563730b7820375cd37490eb40cb6d67e3404bc46c9cc0` | `daee1bee0eae9da35692ad6ae86ae233ed996083745a65e1f1303842181b29c2` |
|
||||
|
||||
All seven relocation offsets and destinations were identical. The first
|
||||
normalized byte divergence was at section offset `+0x55`: target `0x03`,
|
||||
candidate `0x04`; 40 normalized bytes differed in total. The local contexts
|
||||
were:
|
||||
|
||||
- target: `0c84c0740433c0eb038b450c668b55106689065f66c74606`
|
||||
- candidate: `0c84c0740433c0eb040fbf450c668b55106689065f66c74606`
|
||||
|
||||
Decoded at `+0x54`, the target has `eb 03 8b 45 0c`: it jumps over a
|
||||
three-byte `mov eax, dword ptr [ebp+0x0c]`. The candidate has
|
||||
`eb 04 0f bf 45 0c`: it jumps over a four-byte sign-extending word load. The
|
||||
first miss therefore reflects the retained `short move_position_order`
|
||||
formal, not a difference in the Pastudan-derived post-memset store sequence.
|
||||
This is recorded as provenance evidence, not used as a tuning instruction.
|
||||
|
||||
The earlier rejected setup candidate was 144 padded bytes with seven
|
||||
relocations and normalized SHA-256
|
||||
`47b3dc2358c61240e9d48276b9d00caf88d8384cfc505e764f2929cf32ba7491`.
|
||||
The new provenance therefore improved the section extent and relocation
|
||||
topology, but strict byte identity still failed.
|
||||
|
||||
## Restoration and boundary
|
||||
|
||||
The setup body was removed immediately, the baseline object was rebuilt only
|
||||
to restore it, and `tools/coff_compare.py` reconfirmed all five inherited
|
||||
owners exact. The restored source blob is
|
||||
`8de8debb9ac7108acc7352c53e36e305f75d06f7`; the January split object SHA-256
|
||||
is `bb7a70aae881cdf5672ae48c3b9c5b7d0cdcc9a30a90730672f04b71fa1cab5f`.
|
||||
|
||||
Do **not** tune this Pastudan store-order candidate from the observed byte
|
||||
differences and do not retry it. Reopen `_action_alert_setup` only with a new,
|
||||
independent prototype/source-shape adjudication. A defensible future premise
|
||||
would need to establish the likely `long, long, short, pointer` prototype and
|
||||
its cross-translation-unit impact in `source/ai/actions.c`; the byte difference
|
||||
alone is insufficient. The two flush helpers,
|
||||
`_action_alert_update`, `_distance_squared3d`, `_action_alert_perform`, and
|
||||
`_code_00000950` were not compiled in this lane. In particular, current HCEA
|
||||
flush topology is not a new enough premise to override their existing
|
||||
fail-closed boundaries.
|
||||
|
||||
## Documentation and tooling consulted
|
||||
|
||||
- `docs/matching_methodology.md`
|
||||
- `tools/campaign/README.md`
|
||||
- `docs/object_matching_logs/README.md`
|
||||
- the three earlier `action_alert.obj` ledgers
|
||||
- repository `CLAUDE.md` guidance from the canonical, Stian, and Pastudan trees
|
||||
- January `build/split/source/ai/action_alert.obj`
|
||||
- `tools/coff_compare.py` and `tools/campaign/board.py`
|
||||
- current HCEA action-alert history and the Pastudan snapshot named above
|
||||
|
||||
The Discord note that Bungie's fast `ftol` may have been handwritten applies
|
||||
only as Matrix Math provenance. It did not alter this lane's ordinary-C-only
|
||||
admission rules.
|
||||
-193
@@ -1,193 +0,0 @@
|
||||
# Action Alert: restore genuine math-header ownership (2026-09-05)
|
||||
|
||||
## Disposition
|
||||
|
||||
Root has applied the single source-only normalization packet to canonical
|
||||
Action Alert. The actual full canonical Ninja build passes, and the complete
|
||||
stable sweep remains 6,217 exact functions out of 8,245, with zero losses.
|
||||
Root's actual all-section comparison and full tooling/tests also pass.
|
||||
The actual Ninja object is runtime-identical to the reviewed PID candidate:
|
||||
SHA-256 `c15f370e118de1a78c8cbcab7e3d4cd07f255d2c50af6c4b81e7c2cf391b46da`.
|
||||
The exact baseline-to-actual changes are only the three selection transitions
|
||||
and two unreferenced alias removals documented below. All 281 parks validate,
|
||||
the admission audit has no contradictions or revocations, and 288 tests plus
|
||||
26 subtests pass. The pytest cache permission warning affects only caching.
|
||||
Root evidence: `scratch/math-owner-schema-actual-action_alert-20260905.json`,
|
||||
`scratch/math-owner-schema-actual-summary-20260905.json`, and
|
||||
`scratch/math-owner-schema-canonical-first-20260905.json`.
|
||||
|
||||
The first natural candidate retains all
|
||||
11 strict exact functions, the identical existing complete residual, all six
|
||||
runtime data owners, and every gameplay ABI and instruction. No exact bytes
|
||||
are gained or lost. The object remains 11 exact / 1 residual / 0 unwritten,
|
||||
not whole-object Matching.
|
||||
|
||||
This is an ownership correction, not a new gameplay or residual experiment.
|
||||
Canonical production source, headers, configuration and build outputs were
|
||||
not changed by this worker.
|
||||
|
||||
## Source provenance and prior adjudication
|
||||
|
||||
Read in full before the test:
|
||||
|
||||
- `docs/matching_methodology.md` and `tools/campaign/README.md`;
|
||||
- `action_alert_obj_jonas_prefix_recovery.md`;
|
||||
- `action_alert_obj_jonas_safe_geometry_pair_20260826.md`;
|
||||
- `action_alert_obj_jonas_distance_squared_fixed_point_20260826.md`;
|
||||
- `action_alert_obj_jonas_setup_store_order_rejection_20260830.md`;
|
||||
- `action_alert_obj_complete_fuzzy_closeout_20260901.md`;
|
||||
- `action_charge_obj_jonas_math_helper_recovery_rejection_20260826.md`;
|
||||
- `action_charge_obj_jonas_math_helper_recovery_v2_20260826.md`;
|
||||
- `action_charge_obj_jonas_real_random_recovery_20260826.md`;
|
||||
- `game_sound_obj_obstruction_current_owner_boundary_20260905.md`.
|
||||
|
||||
The geometry-recovery ledger explicitly introduced local pre-header aliases
|
||||
and duplicate ordinary external math bodies to add selected code owners while
|
||||
the real gameplay callers were still unwritten. It described the macros as
|
||||
duplicate-definition avoidance; they nevertheless changed ordinary COMDAT
|
||||
ownership and now materialize two additional alias-named helper bodies.
|
||||
The complete 20260901 reconstruction introduced the genuine gameplay uses.
|
||||
|
||||
The old distance fixed point tested a fourth renamed wrapper, not removal of
|
||||
the existing alias layer to restore normal header topology. The old setup and
|
||||
next-position source-shape exhaustion is unrelated and is not reopened.
|
||||
No prior natural owner-header normalization experiment is documented in these
|
||||
ledgers. The new concrete premise is the demonstrated current canonical
|
||||
LNK2005 from Action Alert's ordinary selection-1 duplicate when natural real
|
||||
callers in Game Sound and Observer emit the same header API as selection 2.
|
||||
|
||||
`source/math/real_math.h` owns the actual APIs and bodies:
|
||||
|
||||
- line1027: `__inline real_vector3d *vector_from_points3d(...)`;
|
||||
- line1049: `__inline real magnitude_squared3d(...)`;
|
||||
- line1090: `distance_squared3d`, which genuinely invokes both above;
|
||||
- line1359: `__inline real real_random_range(...)`.
|
||||
|
||||
`source/ai/actions.h:12` already includes that header, and Action Alert also
|
||||
explicitly includes it. The existing distance callers in update, next-position
|
||||
and perform plus the random-range caller in perform naturally expose all
|
||||
three helpers. No synthetic caller, forced-inline annotation, compiler flag,
|
||||
header edit, or code-generation control is required.
|
||||
|
||||
## Exact minimal edit
|
||||
|
||||
Apply only the three replacement records in
|
||||
`scratch/action_alert_natural_math_owners_20260905.edits.json` to
|
||||
`source/ai/action_alert.c`:
|
||||
|
||||
1. Remove three pre-include `#define original original_inline` aliases.
|
||||
2. Remove their three corresponding `#undef` lines.
|
||||
3. Remove the duplicate ordinary external definitions of real_random_range,
|
||||
vector_from_points3d and magnitude_squared3d.
|
||||
|
||||
Every include, gameplay body, private declaration, type, constant, enum, and
|
||||
call remains untouched. This restores existing owner APIs; it does not add
|
||||
inlining or relax the January point_from_line3d schedule.
|
||||
|
||||
## First natural gate and full runtime audit
|
||||
|
||||
Commands from the canonical worktree, with ordinary per-TU flags:
|
||||
|
||||
```text
|
||||
python tools/campaign/gate.py source/ai/action_alert --all --out scratch/action-alert-natural-math-baseline-replay-20260905.obj --forbid-emitted-symbol _point_from_line3d
|
||||
python tools/campaign/gate.py source/ai/action_alert --edits scratch/action_alert_natural_math_owners_20260905.edits.json --all --out scratch/action-alert-natural-math-first-20260905.obj --forbid-emitted-symbol _point_from_line3d
|
||||
python scratch/action_alert_natural_math_owner_audit_20260905.py
|
||||
python scratch/action_alert_natural_math_link_review_20260905.py --scan --link
|
||||
```
|
||||
|
||||
Exactly one untouched baseline replay and one natural changed compile were
|
||||
used. No source retry followed. Both gates report 11E/1R/0U and no forbidden
|
||||
point_from_line3d owner. The residual next-position remains 768 candidate
|
||||
versus 784 target padded bytes; its complete section fingerprint is unchanged.
|
||||
|
||||
The complete all-section audit includes anonymous/code/data/debug/directive
|
||||
sections, COMMON and symbol inventories, offsets, storage and type, section
|
||||
flags and selection, and ordered relocations including full target-symbol
|
||||
metadata. It does not mistake function-only equality for whole-owner equality.
|
||||
|
||||
- Target:12 code owners,6 data owners.
|
||||
- Actual baseline and untouched replay:14 code owners,6 data owners.
|
||||
- Candidate:12 code owners,6 data owners.
|
||||
- No new runtime owner, no COMMON owner or COMMON change.
|
||||
- The only removed runtime owners are `_vector_from_points3d_inline` and
|
||||
`_magnitude_squared3d_inline`, each48 padded bytes. Neither exists in January.
|
||||
- The only inherited runtime changes are COMDAT selection1 to selection2 for
|
||||
the three actual public math helpers. Each is otherwise completely identical
|
||||
in bytes, ordered relocations, symbol metadata/offsets and section flags.
|
||||
- All other inherited code, data and runtime records are completely identical,
|
||||
including the parked body; there is not even a compiler-local-label change.
|
||||
- Actual baseline and untouched PID replay have no runtime differences.
|
||||
- COFF runtime header characteristics are unchanged. Debug/output-path records
|
||||
are separately preserved in the raw audit and are not runtime credit.
|
||||
|
||||
The target selection1 metadata is retained in the audit. This packet does not
|
||||
patch csplit metadata or claim that its original source-object selection was
|
||||
recovered from the linked January image. The natural header source generates
|
||||
ordinary select-any owners and repairs real current-source ownership debt.
|
||||
|
||||
## All-owner census and ordinary link checks
|
||||
|
||||
The census parsed all833 configured January targets and572 actual canonical
|
||||
bases, with zero errors. Among current base definitions:
|
||||
|
||||
| Helper | Base owners | Selection-1 owners |
|
||||
|---|---:|---|
|
||||
| vector_from_points3d |51|Action Alert only|
|
||||
| magnitude_squared3d |67|Action Alert only|
|
||||
| real_random_range |8|Action Alert only|
|
||||
|
||||
Every other base copy is selection2. Both alias-named extras exist only in
|
||||
Action Alert; there are zero incoming relocations to either alias across all
|
||||
target and base objects. Their removal cannot leave a referenced alias owner
|
||||
unresolved.
|
||||
|
||||
All magnitude and random-range copies have the January size/hash. Fifty
|
||||
vector copies have the January hash; the existing Breakable Surfaces copy has
|
||||
hash `a947d351c7b0abf577d0b6e41f02a4f0a7418104d3099e62f6835a862b355b57`.
|
||||
That frozen48-byte/zero-relocation copy differs only by moving the argument
|
||||
load `mov edx,[ebp+8]` before rather than after the first FLD. All26 decoded
|
||||
instructions and dataflow otherwise agree. It uses the actual real_math.h
|
||||
API and is semantically/ABI equivalent, not byte-identical. No expression or
|
||||
source change was made to suppress or force this ordinary pooled copy.
|
||||
|
||||
Ordinary XDK Link.Exe `/NOLOGO /DLL /NOENTRY /NODEFAULTLIB` tests with unchanged
|
||||
frozen natural Action Alert + Game Sound and Action Alert + reviewed Observer,
|
||||
each in both input orders, now have no LNK2005. The previous actual-baseline
|
||||
Game Sound pair has LNK2005 in both orders in its durable rejection ledger.
|
||||
The new runs still end in expected unrelated LNK1120 unresolveds (57 for Game
|
||||
Sound,40 for Observer), and none produces a DLL. Thus this is a passed bounded
|
||||
duplicate-symbol check, not successful whole-link proof. No /FORCE, /IGNORE,
|
||||
object patches, synthetic stubs, header shim or linker accommodation is used.
|
||||
|
||||
## Frozen evidence
|
||||
|
||||
All following paths are relative to the canonical worktree.
|
||||
|
||||
| Artifact | SHA-256 |
|
||||
|---|---|
|
||||
| scratch/action-alert-natural-math-target-20260905.obj |351ff0de9ddfea9b3c03a9038abab75b0c4b48290443b33e09c33105b41ab61a|
|
||||
| scratch/action-alert-natural-math-before-20260905.obj |b82fd9a16f40c01fc45ac810240ad9ea9e02287ae629827c01306b17f7e38d30|
|
||||
| scratch/action-alert-natural-math-baseline-replay-20260905.obj |35bbfb9e7f3f0690af27b6772189d4360e1fbddad71ba81b57b98f027397f549|
|
||||
| scratch/action-alert-natural-math-first-20260905.obj |62ffdb7cd1e7c082b6f03216d4c10bc3437a8f3d0d11d01ba454b0981fc8ac44|
|
||||
| scratch/action_alert_natural_math_before_20260905.c |3a57d07c1c1173cb26903ca40da1b4fc714d11779e65e34bfe8e6f7a40e1ce6d|
|
||||
| scratch/action_alert_natural_math_candidate_20260905.c |27d9268805f0e92024ec10304fbb3dee1398d54055cfb01219d8796f7f0f28af|
|
||||
| scratch/action_alert_natural_math_owners_20260905.edits.json |a91e4428803f9cc697e4d06b52abfbe82c69f8425b9d518360dede80a9624374|
|
||||
| scratch/action_alert_natural_math_owner_audit_20260905.json |9c4bcb9e971e188518b8dda1a9ea20d894bfbd56f12e7fd7e7426902a5eef889|
|
||||
| scratch/action_alert_natural_math_all_owners_20260905.json |737872e034ecd35ee428462306ed87cf6b12f244413944be5625f4701c07ac92|
|
||||
| scratch/action_alert_natural_math_ordinary_links_20260905.json |f1b5c5d828edd62cffa6882d9469c59f50c14a2d985547394852c9a4c169d682|
|
||||
|
||||
## Canonical integration status
|
||||
|
||||
Root read the complete source packet, manifest and primary scratch ledger,
|
||||
then applied only the minimal Action Alert source removals. The full canonical
|
||||
Ninja build passes. The complete stable sweep reports 6,217 exact functions
|
||||
out of 8,245, with zero exact losses and no new exact credit from this cleanup.
|
||||
These are actual canonical results, separate from the frozen scratch results
|
||||
above.
|
||||
|
||||
Full actual runtime-owner comparison and the remaining tooling/tests are
|
||||
pending at the time this durable ledger is authored. Root must complete those
|
||||
checks before treating this batch as fully verified. The existing residual
|
||||
and park remain unchanged, and no whole-object completion or new-byte claim
|
||||
is made. The ordinary two-object linker diagnostics above remain bounded
|
||||
duplicate checks, not a successful full-game link.
|
||||
@@ -1,95 +0,0 @@
|
||||
# action_alert.obj — opus5 150K lane, wave w2 (2026-09-14)
|
||||
|
||||
## Baseline and final
|
||||
|
||||
| gate | result |
|
||||
| --- | --- |
|
||||
| baseline real file | `== exact 11 residual 1 unwritten 0`, guard passes |
|
||||
| final real file (unchanged) | `== exact 11 residual 1 unwritten 0`, guard passes, park drift 0, fake scan 0 leads |
|
||||
|
||||
`git diff --stat -- source/ai/action_alert.c` is empty. No credit is claimed.
|
||||
|
||||
## `_action_alert_next_position` (parked, register-allocation)
|
||||
|
||||
Target 784 / 18 relocs / nsha `677fd6cc1a9e66de`; real-file candidate 768 / 18 / `4e16c85b544ded33`.
|
||||
|
||||
### New evidence
|
||||
|
||||
Aligned diff of the real file:
|
||||
|
||||
- January preloads `or eax,0xffffffff` before the `vehicle_passenger` test (3 B).
|
||||
- January's NONE returns are 32-bit (`mov eax,0xffffffff` on the no-position tail, `or eax,-1` in the guard return block at +0x2f8).
|
||||
- The encounter guard jumps past that block because EAX already holds -1.
|
||||
|
||||
Measured VC7 facts:
|
||||
|
||||
- `return NONE;` in a `short` function emits a 16-bit `or ax,0xffff`. So does `return result;` when result is constant-propagated (d7).
|
||||
- Only an assignment to a `short` result variable emits the 32-bit form.
|
||||
|
||||
The function is therefore single-exit (brief section 9 single-exit law). The earlier park probes had not tested this with the complete assignment topology.
|
||||
|
||||
### Shapes
|
||||
|
||||
| shape | result |
|
||||
| --- | --- |
|
||||
| v1: init `result = NONE`, three-way `&&` guard, `if (any) {...}`, `result = next` | 784/18 `2c7d5520` (shrink-wrapped pushes, result in ECX) |
|
||||
| v2: nested guard; v3: result merged into `next_position_index` | identical to v1 |
|
||||
| v4: no init, `else { result = NONE; }`, `if (!any) result = NONE;` | 768/18 `6ac81fbc` (guards merged into one block, no preload) |
|
||||
| v5: nested if/else; n1: `else if (encounter == NONE) result = NONE;` | identical to v4 |
|
||||
| diagnostic d5: guards `return NONE`, init, no-position store, loop `return` | 1 instruction off (`or ax,0xffff`) |
|
||||
| diagnostic ea: ec without the no-position store | frame 0x24, wrong |
|
||||
| **ec / d10** | **strict EXACT 784/18 `677fd6cc`; whole TU 12/12 exact** |
|
||||
|
||||
The ec / d10 body:
|
||||
|
||||
```c
|
||||
short result = NONE;
|
||||
|
||||
if (actor->input.vehicle_passenger || move_position_order == _move_position_order_none)
|
||||
{
|
||||
result = NONE; /* redundant with the initialiser */
|
||||
}
|
||||
else if (actor->meta.encounter_index != NONE)
|
||||
{
|
||||
/* encounter/squad lookup, swarm assert */
|
||||
if (move_position_order == _move_position_order_repeat && current_position_index != NONE)
|
||||
result = current_position_index;
|
||||
else
|
||||
{
|
||||
/* availability scan (unchanged) */
|
||||
if (!any_position_available)
|
||||
result = NONE; /* redundant with the initialiser */
|
||||
else if (move_position_order == _move_position_order_random)
|
||||
result = choose_random_array_element(...);
|
||||
else
|
||||
{
|
||||
/* clamp + do/while traversal (unchanged) */
|
||||
result = next_position_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
```
|
||||
|
||||
Scratch candidate: `scratch/workers/model_animations_actor_stimulus_etc/aa_ec.c` (patch `aa_ec.patch`). Its checks:
|
||||
|
||||
- the 11 siblings stay exact;
|
||||
- the `_point_from_line3d` guard passes;
|
||||
- parkcheck reports drift only on the park itself;
|
||||
- fake scan finds 0 leads (the scanner does not detect redundant stores);
|
||||
- the function set is unchanged.
|
||||
|
||||
### Disposition
|
||||
|
||||
This is not proposed as an admissible reopen. Exactness requires two NONE stores that the initialiser already guarantees. Every non-redundant spelling measured returns to a different fixed point (v1-v5, n1, d11). Brief section 5 prohibits redundant stores. Previous verifiers rejected the `_action_vehicle_desirable` and `_action_obey_command_begin` re-stores. `_extract_sequence` (January-proven redundant logic) was also left parked. This is an **owner-ruling item**.
|
||||
|
||||
### Reopen criterion
|
||||
|
||||
Either of:
|
||||
|
||||
- an owner ruling that admits January-proven redundant default-result stores (land the aa_ec.c body with a disclosure comment and unpark);
|
||||
- a non-redundant spelling that produces the separate 32-bit NONE materialisations.
|
||||
|
||||
## Do-not-repeat
|
||||
|
||||
v1-v5, n1, d11 (no-init explicit else after the encounter branch), and ea.
|
||||
@@ -1,202 +0,0 @@
|
||||
# ActionCharge: authentic math owners and private names (2026-09-06)
|
||||
|
||||
## Result and scope
|
||||
|
||||
Starting at published `71128a19fc9707f678f970e380b97ee3181db05e`, remove the
|
||||
reconstructed ActionCharge-only alias/duplicate-definition packages for
|
||||
`square_root` and `magnitude_squared2d`. Their existing, identical definitions
|
||||
in `source/math/real_math.h` now supply the ordinary source call sites.
|
||||
The header itself is unchanged. No implementation body is rewritten or tuned.
|
||||
|
||||
Both helpers still materialize and remain strict exact on the first natural
|
||||
compile. All **20 inherited exact ActionCharge functions** survive. The
|
||||
688-byte candidate `action_charge_setup` residual is also byte/relocation
|
||||
identical to its pre-trial version; `action_charge_perform` remains unwritten.
|
||||
ActionCharge remains **20 exact / 1 residual / 1 unwritten**, not complete.
|
||||
|
||||
Across the campaign all **6,271 strict functions** survive. Meaningful exact
|
||||
code remains **919,549 bytes**, credited functions **6,225**, matched data
|
||||
**2,061,024 bytes**, and Matching objects **391/833**. This is source-ownership
|
||||
progress, **zero new function/byte credit**. The helper bodies were already
|
||||
counted; changing their owner representation does not count them again.
|
||||
|
||||
## Why this is authentic reconstruction
|
||||
|
||||
The source previously renamed these two header functions before including
|
||||
`actions.h`, undefined the aliases afterwards, and supplied duplicate external
|
||||
C definitions. The historical recovery ledgers explain that those packages
|
||||
were introduced during reconstruction to reproduce selected-object helper
|
||||
ownership. They are not original source evidence. Review included the
|
||||
2026-08-26 math-helper rejection and wave-2 ledgers, real-random recovery,
|
||||
the 2026-08-28 public residual recovery, and 2026-08-29 helper reintegration.
|
||||
|
||||
HCEX's actual debug records authenticate `real_math.h` ownership and report
|
||||
`WasSpecifiedAsInline=true` and `WasInlined=true` for both functions:
|
||||
|
||||
- `square_root`: RVA 0x169DC28, source lines 644-646;
|
||||
- `magnitude_squared2d`: RVA 0x169DC50, source lines 733-739.
|
||||
|
||||
Use `research/tools/DIA2Dump/x64/Release/DIA2Dump.exe -sym <name>` and
|
||||
`-lines <name>` against
|
||||
`research/hcea_jun2011_prototype/payload/Halo CE Anniversary (Jun 24 2011)/HCEX_Release.pdb`,
|
||||
relative to the outer `i-w` workspace. Both line records name
|
||||
`d:\projects\code\hcex\sources\math\real_math.h`, source MD5
|
||||
`DE0F004C6EB037D8BE384822F84E002C`.
|
||||
|
||||
The January symbol atlas at
|
||||
`research/halo-symbol-atlas/symbols/halo_ce/4cc87b45f721270392a96f1674ed2b5cd4a7bb4355faeab4531d1cf1884d9520.jsonl`
|
||||
marks adjacent `normalize2d`, `magnitude3d` and `normalize3d` as inline
|
||||
functions selected from ActionCharge. It omits these smaller two symbols;
|
||||
do not misrepresent that omission as direct January name/inline evidence.
|
||||
January's actual helper bytes and the current header bodies independently
|
||||
agree; the original selected COFF representation is not proof of a hand-written
|
||||
external wrapper in the original C file.
|
||||
|
||||
Current ordinary call sites justify retention without a fabricated anchor:
|
||||
`magnitude2d` calls `square_root(magnitude_squared2d(v))`, and `magnitude3d`
|
||||
calls `square_root` on the three-component squared magnitude. Reuse those
|
||||
unaltered calls and the existing ordinary header definitions. No new inline
|
||||
annotation, static-inline conversion, qualifier, forced emission, new source
|
||||
alias, compiler switch, object patch or comparator exception is introduced.
|
||||
|
||||
## Full compiled-object proof
|
||||
|
||||
Root's complete before/first ordinary COFF fingerprint comparison finds
|
||||
**38 COFF sections: 36 unchanged and exactly two ownership changes**
|
||||
(34 unchanged non-debug sections plus both unchanged debug sections).
|
||||
Only the COMDAT selection of `square_root` and `magnitude_squared2d` changes
|
||||
from NODUPLICATES (1) to SELECT_ANY (2). Every executable/data byte, relocation,
|
||||
symbol name/storage, debug section, COMMON owner and other runtime header
|
||||
property is unchanged. No section is added or removed. The existing selected
|
||||
`point_from_line3d` body is unchanged; there is no new copy or inline scheduling
|
||||
change. The first gate retains both exact helpers and all inherited functions.
|
||||
|
||||
Normalized helper hashes remain:
|
||||
|
||||
- `square_root`, 16 padded bytes, zero relocations:
|
||||
`0717923dacb4356a94553a32f0ba8a314904fae6d7d0bfc42ecc4af6f10415b7`;
|
||||
- `magnitude_squared2d`, 32 padded bytes, zero relocations:
|
||||
`9d8460618a63e41e020b2ce8071486fe278a849abccad44e5ea444da9700d014`.
|
||||
|
||||
The genuine header is unchanged, so no other translation unit needs a source
|
||||
rebuild. A full Ninja run compiles ActionCharge and regenerates the campaign
|
||||
reports. In this owner-only phase, all other current base objects and every
|
||||
selected target remain identical to the frozen baseline. The full strict census has zero
|
||||
gains and zero losses. **650 tests plus 26 subtests** pass; parks remain
|
||||
**297 active / zero stale / zero invalid**. Admission retains five existing
|
||||
rejections and has zero candidates, contradictions or revocations. The source
|
||||
has zero fake-match scanner leads.
|
||||
|
||||
## Current owner census and actual link outcomes
|
||||
|
||||
The complete 572-base-object census now finds 60 `square_root` definitions
|
||||
and 15 `magnitude_squared2d` definitions, **all SELECT_ANY**, with identical
|
||||
target-correct bytes within each family. There is no remaining NODUPLICATES
|
||||
definition for either name. `dot_product2d` remains seven identical definitions:
|
||||
ActionCharge's one NODUPLICATES and six SELECT_ANY copies.
|
||||
|
||||
Root's actual VC7 `/DLL /NOENTRY /NODEFAULTLIB` links of the frozen complete
|
||||
PathObstacles and ActionCharge objects, in both input orders, now report only
|
||||
`dot_product2d` as LNK2005. The previous `square_root` and
|
||||
`magnitude_squared2d` duplicate errors are gone. The expected 23 unrelated
|
||||
unresolved dependencies remain and no successful full engine link is claimed.
|
||||
No forced-multiple-definition flag, object suppression or synthetic stub
|
||||
removes the remaining conflict.
|
||||
|
||||
## Authenticated private names, without behavior changes
|
||||
|
||||
After freezing and verifying the two-owner restoration, a separate `named`
|
||||
phase replaces exactly two address placeholders in declarations, definitions,
|
||||
calls and the symbol comment:
|
||||
|
||||
| January file offset | Old placeholder | Authentic private name |
|
||||
| ---: | --- | --- |
|
||||
| 4304 | `code_000010d0` | `action_charge_find_target_range` |
|
||||
| 9168 | `code_000023d0` | `action_charge_valid_melee_destination` |
|
||||
|
||||
The exact January atlas cited above supplies both names at lines 7 and 14,
|
||||
each attributed to ActionCharge. HCEX Release DIA independently identifies
|
||||
both as static and not specified inline, with source lines 821-854 and 860-901
|
||||
in `d:\projects\code\hcex\sources\ai\action_charge.c`. The source was already
|
||||
static; the two matching `config/symbols.json` entries now record the genuine
|
||||
names and `static: true` rather than csplit's default external ownership.
|
||||
|
||||
The source argument types and all executable statements remain unchanged.
|
||||
In particular, the melee destination's second argument remains
|
||||
`real_point3d const *goal`: HCEX's `short goal` type metadata is contradicted
|
||||
by actual January point loads and by the later decompiler's own corrected
|
||||
body. January reads `[ESI]`, `[ESI+4]` and `[ESI+8]`, while its caller supplies
|
||||
the prop's center of mass. Do not import the erroneous short signature.
|
||||
|
||||
January's helper does not access or write through `melee_target_point`, and
|
||||
the caller never consumes that discarded local. The HCEA semantic body and
|
||||
caller corroborate this. Keeping `(void)melee_target_point;` therefore
|
||||
preserves actual behavior; do not invent an output write or use the parameter
|
||||
name as proof of missing executable logic. Whole-TU optimization could remove
|
||||
historical dead stores, so the audit does not claim to prove the original text
|
||||
never contained an assignment.
|
||||
|
||||
Root's full before-name/after-name fingerprint comparison reports all **38
|
||||
runtime sections unchanged**, once the two authenticated symbol identities
|
||||
are mapped for comparison. No instruction, literal, data, relocation offset,
|
||||
addend, debug record or ownership change exists in the base object beyond
|
||||
those names. The selected target changes names and the two static-storage
|
||||
records. Across all 1,405 current objects, only the ActionCharge base and
|
||||
selected target hashes change; every other object is byte-identical. The
|
||||
full rebuild and strict census again preserve all 6,271 exact functions.
|
||||
This audit-name mapping is not a comparator exception or new byte credit.
|
||||
|
||||
## Remaining boundary
|
||||
|
||||
`dot_product2d` has the same authenticated header-inline provenance, but no
|
||||
live source caller in current ActionCharge. Its real use belongs to the still
|
||||
unwritten `action_charge_perform`. Do not invent a caller or a retention anchor
|
||||
to make an uncalled header definition materialize. Its old duplicate-definition
|
||||
package remains outside this two-owner restoration and needs the genuine
|
||||
caller closure. Other inherited ActionCharge aliases/prototype
|
||||
debts are not certified by this patch, and the large residual is not reopened.
|
||||
|
||||
This does not claim a complete engine link or whole-object admission. It
|
||||
reconciles two real duplicate-owner families while preserving all compiled
|
||||
behavior and accounting. Active Opus implementations and donor worktrees are
|
||||
untouched. Original binary evidence and temporary link outputs stay local.
|
||||
|
||||
## Frozen evidence
|
||||
|
||||
Two independent post-implementation audits pass. The owner audit replays the
|
||||
full before/first COFF comparison, verifies all 572 named-phase base objects,
|
||||
and runs the actual VC7 diagnostic links in both orders. Its script hard-pins
|
||||
the imported comparison tools and linker. The separate private-name audit
|
||||
checks all section and relocation records, caller targets/addends, exact source
|
||||
and config changes, and all 1,405 current base/selected object hashes.
|
||||
|
||||
- Owner replay script: `scratch/action_charge_two_owner_postimplementation_audit_20260906.py`,
|
||||
SHA-256 `0cc2e805f87cc55920a6bc3202aa284185e36374cbd7eb335e5c1ad15e86fa9d`.
|
||||
- Independent owner report: `scratch/action-charge-two-owner-postimplementation-audit-final-20260906.json`,
|
||||
SHA-256 `096b850bd6c00d0e3b8692dea0fbe0ad4e4789556a868a78ab84ed9b8dc9a397`.
|
||||
- Independent private-name report: `scratch/action-charge-private-name-postimplementation-independent-20260906.json`,
|
||||
SHA-256 `380291ccd1dd183ca88231dd08b2b68f5aae04639e60fdfffc767006228b11a4`.
|
||||
|
||||
These reports are local frozen evidence, not target binaries to distribute.
|
||||
Both audits preserve the distinction between the remaining `dot_product2d`
|
||||
link conflict and the two genuinely resolved duplicate-owner families.
|
||||
|
||||
- Baseline: `scratch/action-charge-math-owner-before-20260906.json`,
|
||||
SHA-256 `34ccf1a6d5e32b4348364235802ba488b62c48317e83c45d0317f9fdc93fa4dc`.
|
||||
- First: `scratch/action-charge-math-owner-first-20260906.json`,
|
||||
SHA-256 `fd64316616dca63d976bd3c9ca367b9061a69e80ae0c28f27e61a443cdd210d5`.
|
||||
- Final: `scratch/action-charge-math-owner-final-20260906.json`,
|
||||
SHA-256 `a81dcaced90b94c6726aa7004b04bb56213c2f2208efe21a8b1898771183d7c5`.
|
||||
- Before C/base object: `e8096e28a0a821ae5f97b0461c61ae6f828f51037b0cb62b75f5b1d8fb0be366` /
|
||||
`45c5386b96ba99b67834dd3ffd85e797dc5fdb8385db4cd4ab1e73d006f8df6d`.
|
||||
- Pre-name two-owner C/base object: `5f182feceec9ccf33d2d8eade40c88db42c697cbfe4d26f5682fce3121bd193a` /
|
||||
`8c19c85deb223ff89aeaed6ff768e192139e040496c853b1fb91e31eef5c315b`.
|
||||
- Unchanged math header: `4e640d1be7b2c843dc7c9acb198afcd5d7d390eb310e5e14eedd484cf99535d4`.
|
||||
- `scratch/action-charge-math-owner-{before,first}-stable-20260906.json`:
|
||||
6,271 strict functions, zero gains/losses.
|
||||
- Named final: `scratch/action-charge-math-owner-named-20260906.json`,
|
||||
SHA-256 `1d4305f1d603e619889f2e94dd282ca40a364d3115ea447ddb579a7c7e257a88`.
|
||||
- Named final C: `75961e822a451f5d23910def9cc4661e1fbd0bdefa9caa314f776cf0aa21e81d`;
|
||||
base object: `cecd4d02fc1dbcf8a355ef289899f7230bd3463b3299abe486cb36ee871ef371`;
|
||||
selected target: `a906f0ec24b0313a056d4a413eaf85ee32f22f02c45878261bcae4521bfa63c8`;
|
||||
symbols configuration: `57d80ec4aa5d567067f97ac9f4552bba4d85dc777201d480fdadd47f93b06ccf`.
|
||||
@@ -1,68 +0,0 @@
|
||||
# `action_charge.obj` helper reintegration — 2026-08-29
|
||||
|
||||
## Result
|
||||
|
||||
The canonical source now measures **20/22 strict-exact functions** and
|
||||
**1,984/6,176 strict-exact padded bytes**. This restores the best historical
|
||||
function frontier while preserving the later public lifecycle, control, and
|
||||
math-helper recoveries.
|
||||
|
||||
Relative to the prior canonical 17/22 object, this is a non-regressing gain of
|
||||
three functions and 640 padded bytes:
|
||||
|
||||
| Function | Padded bytes | Result |
|
||||
| --- | ---: | --- |
|
||||
| `_code_000010d0` | 272 | strict exact |
|
||||
| `_collision_test_line` | 80 | strict exact |
|
||||
| `_code_000023d0` | 288 | strict exact |
|
||||
|
||||
The two remaining functions are classified honestly:
|
||||
|
||||
- `_action_charge_perform`: unwritten, 3,248 padded bytes.
|
||||
- `_action_charge_setup`: readable typed-C residual, 688 candidate bytes and
|
||||
20 relocations versus the 944-byte/29-relocation target.
|
||||
|
||||
## Provenance and recovery
|
||||
|
||||
The archived ledger at commit
|
||||
`677defb9d9b4dd0ac4f20bc2c5dbd53bf3e8d7f5` recorded a measured 20/22
|
||||
experiment, but deliberately restored its source before commit. Its surviving
|
||||
notes identified the accepted source topology for the two anonymous helpers:
|
||||
|
||||
- the range helper uses zero textually on the left for nonnegative checks and
|
||||
keeps the suicidal/non-suicidal melee limits in separate branches;
|
||||
- the destination helper calls the ordinary typed `collision_test_line`
|
||||
wrapper and brackets the call with the AI-melee collision-user scope.
|
||||
|
||||
The readable HCEA donor files were used only to recover behavior and named
|
||||
field access. A complete typed `action_charge_setup` supplies the natural call
|
||||
sites needed for VC7 to reproduce the target's internal register calling
|
||||
convention for both anonymous helpers. No standalone ABI shim, raw offset,
|
||||
representation cast, object patch, compiler flag, or comparator exception was
|
||||
used.
|
||||
|
||||
## Verification
|
||||
|
||||
Commands run from the canonical worktree:
|
||||
|
||||
```text
|
||||
python tools/campaign/gate.py source/ai/action_charge --all
|
||||
ninja build\base\source\ai\action_charge.obj
|
||||
python tools/campaign/board.py source/ai/action_charge
|
||||
python tools/campaign/board.py
|
||||
git diff --check -- source/ai/action_charge.c
|
||||
```
|
||||
|
||||
Measured output:
|
||||
|
||||
```text
|
||||
UNWRITTEN 3248 _action_charge_perform
|
||||
residual 944 _action_charge_setup [size 688!=944, relocs 20!=29, sha]
|
||||
== exact 20 residual 1 unwritten 1 (of 22 listed)
|
||||
|
||||
objects 275/619 fully exact; bytes 651111/1922669; fns 4699/8246
|
||||
```
|
||||
|
||||
The campaign totals increase from 650,471 to 651,111 strict-exact padded bytes
|
||||
and from 4,696 to 4,699 strict-exact functions, with the exact-object count
|
||||
unchanged at 275.
|
||||
-125
@@ -1,125 +0,0 @@
|
||||
# `action_charge.obj` Jonas math-helper recovery rejection — 2026-08-26
|
||||
|
||||
## Decision
|
||||
|
||||
This frozen wave is **rejected wholesale**. All twelve requested math helpers
|
||||
reproduced their January padded bytes and relocation identities on the only
|
||||
ordinary candidate compile, but the candidate also emitted an out-of-line
|
||||
`_magnitude_squared3d` COMDAT that failed the required linker-level ownership
|
||||
gate. No production source from this wave is retained and no function or data
|
||||
credit is claimed from it.
|
||||
|
||||
The rejection is useful new evidence: the canonical readable body of
|
||||
`magnitude3d` is byte-correct after inlining, but spelling it as a call to the
|
||||
header `magnitude_squared3d` helper causes VC7 to materialize an unwanted
|
||||
out-of-line copy. A later frozen wave may reopen only with a source topology
|
||||
that removes that helper reference before compilation.
|
||||
|
||||
## Frozen provenance
|
||||
|
||||
- Branch: `jonas/action-charge-math-recovery-20260826`
|
||||
- Base commit: `19ed6902ffa755c9b7c7b01cb926ea8af49d5d14`
|
||||
- January target object SHA-256:
|
||||
`76C4C0B62850FFAA42FE5027C3E68B2CC42F7640C1156342C9A9CC4D1125AFEA`
|
||||
- Clean pre-wave base object SHA-256:
|
||||
`C0683E96025CBAC9980D9779786C89B69164502336E7ABCA23874EB6835C40CE`
|
||||
- Frozen candidate source Git blob:
|
||||
`ffc743d088b2c065a53826300514a4e3122ea500`
|
||||
- Frozen candidate source physical SHA-256:
|
||||
`769194E601F4CC9132B8AB90CB825DE07A452896647328179D7D5CC3AC771C08`
|
||||
- XDK 3911 compiler SHA-256:
|
||||
`483E00C47BB08D699475A642BCFF15B5B2036350B31C540E88A506BAF101DA11`
|
||||
- Splitter SHA-256:
|
||||
`708F957C37CAA66DF90ADE35AD3D1E65E2617E2CC2C8C2CCF68D8BF5CB20E752`
|
||||
- Candidate object: 3,839 bytes, raw SHA-256
|
||||
`146B19F6DB3DF4163904B15CD5ABD3AB2E0FBA548CB7F2792E100F3425CE306C`.
|
||||
- Compiler flags and include search path were unchanged:
|
||||
`/O2 /Oy- /DDEBUG /Dxbox`.
|
||||
|
||||
The source passed the XDK `/Zs` syntax-only gate. A Ninja dry run then exposed
|
||||
exactly one `CL build\base\source\ai\action_charge.obj` edge. It was invoked
|
||||
once and its first artifact was preserved before any comparison. No spelling,
|
||||
declaration, scheduling, compiler, or flag retry followed.
|
||||
|
||||
## Strict-exact evidence from the rejected artifact
|
||||
|
||||
The hardened comparator reported `all_equal: true` for all twelve new helpers
|
||||
and the three inherited accepted functions. The twelve helpers contribute 479
|
||||
meaningful / 544 padded target bytes and six relocations.
|
||||
|
||||
| Function | Padded bytes | Relocs | Normalized SHA-256 |
|
||||
| --- | ---: | ---: | --- |
|
||||
| `_square_root` | 16 | 0 | `0717923dacb4356a94553a32f0ba8a314904fae6d7d0bfc42ecc4af6f10415b7` |
|
||||
| `_scale_vector2d` | 32 | 0 | `496d82c0615b4ec0cb4211dd21dfbf507d8959357a60895b9fd4d930b554cf95` |
|
||||
| `_magnitude_squared2d` | 32 | 0 | `9d8460618a63e41e020b2ce8071486fe278a849abccad44e5ea444da9700d014` |
|
||||
| `_magnitude2d` | 32 | 0 | `17d586569ec882a34a898e8a589fe5140e8d8b79b85e2fd4e7816dfe6210d3fa` |
|
||||
| `_normalize2d` | 80 | 3 | `8a5659d5dd494fe2d1d880057d1836185ebfb8e81d9d63362a43e6a2cb287890` |
|
||||
| `_dot_product2d` | 32 | 0 | `defea20c9a86f0deda350c23260a0e093b08da31a2cbcd5e5c08b17164579415` |
|
||||
| `_point_from_line3d` | 48 | 0 | `9b763841f8519177ac2d3fd471226972b9fa92cf1e9061e9f92359077dc82741` |
|
||||
| `_scale_vector3d` | 48 | 0 | `6436919fbdc80b5d5fe76d9c92fa146e5ac7d3b4637c9b75aaa62401f0c54a3b` |
|
||||
| `_magnitude3d` | 48 | 0 | `114f10e7ee4543446daaaafc859a4ec729ba6c8c74c38825d05bd0f00a42352c` |
|
||||
| `_normalize3d` | 96 | 3 | `67fbd33f204d0c93cce135fcfd37d4ce5b443642edc6ad99230846b91c893e5b` |
|
||||
| `_dot_product3d` | 32 | 0 | `d564ef69fd99449fdfc29d59d0d844fb17df91369277eaba9574e7c8c3d2ae68` |
|
||||
| `_subtract_vectors3d` | 48 | 0 | `1d706c27e470449c1ac16f5c5ff47c98ee2be96426f2b8bb949ba79e9d764cac` |
|
||||
|
||||
The inherited sentinels remained strict exact:
|
||||
|
||||
| Function | Padded bytes | Relocs | Normalized SHA-256 |
|
||||
| --- | ---: | ---: | --- |
|
||||
| `_action_charge_begin` | 80 | 3 | `c78c6feeb10fda8857834f5264614aa976498059590ee08304aef25f21af8bf3` |
|
||||
| `_action_charge_update` | 80 | 2 | `f2591b2de350c20aefef42c38623875dca494bb46a51d06c6dcd5947b035976e` |
|
||||
| `_real_random` | 16 | 2 | `50eeeb3dc58069325659d8bc0b6f2c17bb9f4fdce278b2f1a37edb64f4fcc60c` |
|
||||
|
||||
Both normalize functions reproduced the target relocation offsets, types,
|
||||
destinations, addends, and local ownership for `0.0f`, `1.0f`, and the
|
||||
double-precision epsilon literal. The three emitted target-owned `.rdata`
|
||||
COMDATs were also strict exact: four bytes at
|
||||
`__real@00000000`, four bytes at `__real@3f800000`, and eight bytes at
|
||||
`__real@3f1a36e2e0000000`. They receive no credit because the wave is rejected.
|
||||
|
||||
## Ownership contradiction
|
||||
|
||||
The candidate additionally emitted `_magnitude_squared3d` as a 48-byte,
|
||||
zero-relocation, select-any code COMDAT. No candidate relocation refers to the
|
||||
out-of-line copy. Its normalized bytes are strict exact against the January
|
||||
canonical owner in `source/ai/action_alert.obj`:
|
||||
|
||||
- 48 padded bytes;
|
||||
- zero relocations;
|
||||
- normalized SHA-256
|
||||
`0d04579096eeab3a1c45f87774e1eb20ce4856dbac219f624a855e8c9ae99725`.
|
||||
|
||||
That cross-object byte equality is insufficient. The acceleration playbook
|
||||
allows a candidate-only helper COMDAT only when the ordinary linker discards
|
||||
it. A direct XDK 3911 link of the January canonical `action_alert.obj` and the
|
||||
candidate `action_charge.obj` was run in both input orders. Both orders fail:
|
||||
|
||||
```text
|
||||
action_charge.obj : error LNK2005: _magnitude_squared3d already defined in action_alert.obj
|
||||
action_alert.obj : error LNK2005: _magnitude_squared3d already defined in action_charge.obj
|
||||
fatal error LNK1169: one or more multiply defined symbols found
|
||||
```
|
||||
|
||||
Thus this is not an admissible discardable-helper representation difference.
|
||||
The target canonical owner is a no-duplicates COMDAT, and the candidate copy
|
||||
cannot coexist with it. The wave fails before campaign admission regardless of
|
||||
the twelve function-byte successes.
|
||||
|
||||
## Atomic restoration and reopen criterion
|
||||
|
||||
The complete macro/definition package was removed after the ownership failure.
|
||||
The production source is restored exactly to:
|
||||
|
||||
- Git blob `3e76470cf8be066072239845cbf08e37aeffa458`;
|
||||
- physical SHA-256
|
||||
`3B798CC7F02BCC50741E88D6C735E9F12780DC4AE645BC69DD48262A6E6D67EB`.
|
||||
|
||||
Only this rejection ledger is retained. There is no config, comparator,
|
||||
compiler, protected-file, source, or matching-label change and no push.
|
||||
|
||||
The link failure is genuinely new evidence. A new wave may test one frozen
|
||||
topology: keep the twelve exact external helper bodies, but express
|
||||
`magnitude3d` directly as the already-inlined three-component squared-magnitude
|
||||
expression so the header `_magnitude_squared3d` body is never referenced and
|
||||
VC7 has no reason to materialize the extra COMDAT. That is a new evidence wave,
|
||||
not a retry of this rejected source.
|
||||
-183
@@ -1,183 +0,0 @@
|
||||
# `action_charge.obj` Jonas math-helper recovery wave 2 — 2026-08-26
|
||||
|
||||
## Outcome
|
||||
|
||||
This wave recovers twelve math helpers as strict exact and retains all three
|
||||
previously accepted `action_charge.obj` functions. The object advances from
|
||||
3/22 to **15/22 strict-exact functions**. The twelve-function gain is 479
|
||||
meaningful / 544 padded code bytes and six relocations. The object remains
|
||||
`NonMatching`; none of the seven absent behavioral functions is claimed.
|
||||
|
||||
Three target-owned read-only constant COMDATs, sixteen bytes total, are also
|
||||
present with exact bytes and ownership. The ordinary report may credit those
|
||||
sections directly; no semantic exception or manual data ledger entry is used.
|
||||
|
||||
## Why this is a second evidence wave
|
||||
|
||||
The first frozen recovery candidate made all twelve helper bodies byte-exact,
|
||||
but VC7 also materialized an unwanted select-any `_magnitude_squared3d`
|
||||
out-of-line helper. A direct XDK link against the January canonical owner in
|
||||
`action_alert.obj` failed with `LNK2005` in both input orders. That entire
|
||||
candidate was removed and the rejection is recorded in
|
||||
`action_charge_obj_jonas_math_helper_recovery_rejection_20260826.md`.
|
||||
|
||||
The linker failure supplied genuinely new evidence. Wave 2 therefore froze one
|
||||
new topology: `magnitude3d` spells the already-inlined three-component squared
|
||||
magnitude expression directly. Its emitted `_magnitude3d` instructions remain
|
||||
identical, but no source reference remains from which VC7 can materialize the
|
||||
rejected helper owner.
|
||||
|
||||
## Frozen provenance and compile discipline
|
||||
|
||||
- Branch: `jonas/action-charge-math-recovery-v2-20260826`
|
||||
- Evidence base: `511d251d3765b1caac824a47ed8bf330c677cc85`
|
||||
- January target object SHA-256:
|
||||
`76C4C0B62850FFAA42FE5027C3E68B2CC42F7640C1156342C9A9CC4D1125AFEA`
|
||||
- Clean pre-wave base object SHA-256:
|
||||
`C0683E96025CBAC9980D9779786C89B69164502336E7ABCA23874EB6835C40CE`
|
||||
- Frozen candidate source Git blob:
|
||||
`64818f49f816817883be1621a9737166c7615bb7`
|
||||
- Frozen candidate source physical SHA-256:
|
||||
`AF8166FC414F459190CE9720B41E5A3BA7858FAFEEB59B226740CF377D0C7E02`
|
||||
- XDK 3911 `CL 13.00.9254.1` SHA-256:
|
||||
`483E00C47BB08D699475A642BCFF15B5B2036350B31C540E88A506BAF101DA11`
|
||||
- Splitter SHA-256:
|
||||
`708F957C37CAA66DF90ADE35AD3D1E65E2617E2CC2C8C2CCF68D8BF5CB20E752`
|
||||
- Flags: `/O2 /Oy- /DDEBUG /Dxbox`; project include list unchanged.
|
||||
- First candidate object: 3,676 bytes, raw SHA-256
|
||||
`638CE42681DB10907F0C847F2679806E07091A34085E4EE0D50E1AC3DB1E1E67`.
|
||||
|
||||
The frozen source passed the XDK `/Zs` syntax-only gate. Ninja dry-run output
|
||||
contained exactly one `CL build\base\source\ai\action_charge.obj` edge. That
|
||||
edge was invoked once, and the first object was copied into the frozen audit
|
||||
packet before comparison. The accepted object subsequently reports no work.
|
||||
There was no same-wave source, flag, declaration, scheduling, or compiler
|
||||
retry.
|
||||
|
||||
## Strict function evidence
|
||||
|
||||
The hardened comparator requires padded size, normalized bytes, relocation
|
||||
address/type, resolved destination, addend, and ownership to agree. It reports
|
||||
`all_equal: true` for the twelve recovered helpers and all three inherited
|
||||
sentinels.
|
||||
|
||||
| Function | Padded bytes | Relocs | Normalized SHA-256 |
|
||||
| --- | ---: | ---: | --- |
|
||||
| `_action_charge_begin` | 80 | 3 | `c78c6feeb10fda8857834f5264614aa976498059590ee08304aef25f21af8bf3` |
|
||||
| `_action_charge_update` | 80 | 2 | `f2591b2de350c20aefef42c38623875dca494bb46a51d06c6dcd5947b035976e` |
|
||||
| `_square_root` | 16 | 0 | `0717923dacb4356a94553a32f0ba8a314904fae6d7d0bfc42ecc4af6f10415b7` |
|
||||
| `_scale_vector2d` | 32 | 0 | `496d82c0615b4ec0cb4211dd21dfbf507d8959357a60895b9fd4d930b554cf95` |
|
||||
| `_magnitude_squared2d` | 32 | 0 | `9d8460618a63e41e020b2ce8071486fe278a849abccad44e5ea444da9700d014` |
|
||||
| `_magnitude2d` | 32 | 0 | `17d586569ec882a34a898e8a589fe5140e8d8b79b85e2fd4e7816dfe6210d3fa` |
|
||||
| `_normalize2d` | 80 | 3 | `8a5659d5dd494fe2d1d880057d1836185ebfb8e81d9d63362a43e6a2cb287890` |
|
||||
| `_dot_product2d` | 32 | 0 | `defea20c9a86f0deda350c23260a0e093b08da31a2cbcd5e5c08b17164579415` |
|
||||
| `_point_from_line3d` | 48 | 0 | `9b763841f8519177ac2d3fd471226972b9fa92cf1e9061e9f92359077dc82741` |
|
||||
| `_scale_vector3d` | 48 | 0 | `6436919fbdc80b5d5fe76d9c92fa146e5ac7d3b4637c9b75aaa62401f0c54a3b` |
|
||||
| `_magnitude3d` | 48 | 0 | `114f10e7ee4543446daaaafc859a4ec729ba6c8c74c38825d05bd0f00a42352c` |
|
||||
| `_normalize3d` | 96 | 3 | `67fbd33f204d0c93cce135fcfd37d4ce5b443642edc6ad99230846b91c893e5b` |
|
||||
| `_dot_product3d` | 32 | 0 | `d564ef69fd99449fdfc29d59d0d844fb17df91369277eaba9574e7c8c3d2ae68` |
|
||||
| `_subtract_vectors3d` | 48 | 0 | `1d706c27e470449c1ac16f5c5ff47c98ee2be96426f2b8bb949ba79e9d764cac` |
|
||||
| `_real_random` | 16 | 2 | `50eeeb3dc58069325659d8bc0b6f2c17bb9f4fdce278b2f1a37edb64f4fcc60c` |
|
||||
|
||||
The two normalize functions reproduce all six January DIR32 relocation slots:
|
||||
|
||||
- `_normalize2d`: `+0x21`, `+0x2E`, `+0x46`;
|
||||
- `_normalize3d`: `+0x2C`, `+0x39`, `+0x59`;
|
||||
- destinations in both cases: the double epsilon, `1.0f`, and `0.0f`, with
|
||||
zero addends and target-identical local ownership.
|
||||
|
||||
## Whole-object ownership audit
|
||||
|
||||
The January target owns 22 code sections. The candidate owns exactly fifteen,
|
||||
all of which are target-owned and strict exact. It has **no candidate-only code
|
||||
owner**. The seven target-only functions are exactly:
|
||||
|
||||
1. `_code_000010d0`
|
||||
2. `_action_charge_control`
|
||||
3. `_action_charge_is_leaping`
|
||||
4. `_collision_test_line`
|
||||
5. `_action_charge_perform`
|
||||
6. `_code_000023d0`
|
||||
7. `_action_charge_setup`
|
||||
|
||||
The candidate owns no `.data`, `.bss`, COMMON symbol, or other writable runtime
|
||||
storage. Its only defined runtime non-function owners are these target-owned
|
||||
select-any `.rdata` COMDATs:
|
||||
|
||||
| Symbol | Bytes | Relocs | Normalized SHA-256 |
|
||||
| --- | ---: | ---: | --- |
|
||||
| `__real@00000000` | 4 | 0 | `df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119` |
|
||||
| `__real@3f800000` | 4 | 0 | `e00e5eb9444182f352323374ef4e08ebcb784725fdd4fd612d7730540b3e0c8c` |
|
||||
| `__real@3f1a36e2e0000000` | 8 | 0 | `564be83b341e452f4492fa81f7d5f215f446119f583c33a94b619cd1ee7287fd` |
|
||||
|
||||
The `_magnitude_squared3d` symbol and section are absent. Diagnostic XDK links
|
||||
of the complete January `action_alert.obj` target with the candidate object
|
||||
succeed in both input orders under `/FORCE:UNRESOLVED` (exit 0); the expected
|
||||
unresolved project dependencies remain warnings, while the wave-1 `LNK2005`
|
||||
and `LNK1169` ownership failures are gone.
|
||||
|
||||
## Source and policy review
|
||||
|
||||
The retained code is ordinary typed C. It keeps one parameter per line, uses
|
||||
`void` on its own line for the no-argument function, and gives every function
|
||||
an explicit return. It introduces no assembly, `register`, `volatile`, pragma,
|
||||
attribute, forced inlining, barrier, byte forcing, raw address, raw object/tag
|
||||
cast, pointer/integer reconstruction, union pun, or undefined behavior. No
|
||||
protected Units or game-engine file is touched.
|
||||
|
||||
The isolated tooling suite passes 179/179 tests. `git diff --check` is clean,
|
||||
the candidate object dry run reports no work, and the changed production path
|
||||
is only `source/ai/action_charge.c`. Whole-campaign reports, regression
|
||||
snapshot/check, and cumulative-tree validation are recorded in a committed
|
||||
replay after integration.
|
||||
|
||||
## Committed cumulative replay
|
||||
|
||||
The evidence branch was merged into `jonas/units-integration-20260824` at
|
||||
`b08d30922a82ee675400a8d9f78aaef99dbe8dcf`. The cumulative compiler replay
|
||||
produced a 3,676-byte object with raw SHA-256
|
||||
`C11BB3BF615299968C93F4BB4857A12B4955D11B8255C6A45F99508E63595CDF`.
|
||||
Raw object hashes differ normally with the COFF timestamp; hardened comparison
|
||||
again reports `all_equal: true` for all fifteen code owners and all three
|
||||
constant owners. The cumulative owner table still contains exactly fifteen
|
||||
target-owned functions and no candidate-only function, `.data`, `.bss`, or
|
||||
COMMON owner.
|
||||
|
||||
The regenerated ordinary report records the unit as:
|
||||
|
||||
- 15/22 matched functions;
|
||||
- 643/6,032 meaningful code bytes;
|
||||
- twelve functions and 479 code bytes above the pre-wave 3/22 state;
|
||||
- 256 target data bytes represented as one aggregate report section.
|
||||
|
||||
The three constant COMDATs are independently strict exact, but the ordinary
|
||||
report does not expose partial per-COMDAT data credit inside its aggregate
|
||||
`.rdata` measure. The semantic-data gate intentionally permits incomplete-unit
|
||||
credit only when a verified owner spans the entire remaining data gap. These
|
||||
three owners span 16 of 256 bytes, so matched campaign data remains unchanged;
|
||||
no exception, accounting change, or overstated 16-byte claim is introduced.
|
||||
|
||||
A committed `tools.regression_gate` snapshot/check for
|
||||
`source/ai/action_charge` reports:
|
||||
|
||||
- all fifteen functions `still_exact`;
|
||||
- `changed_nonexact: []`;
|
||||
- `newly_exact: []` after the committed snapshot;
|
||||
- no failures and no warnings.
|
||||
|
||||
The cumulative verification set passes:
|
||||
|
||||
- `halobetacache_build libcmt_build`: no work after the replay object;
|
||||
- semantic report: 470 units, 4,288 functions evaluated, 4,210 accepted exact,
|
||||
and zero unit errors;
|
||||
- campaign progress: 507,503 / 2,198,102 code bytes, 4,184 / 11,060
|
||||
functions, and 1,836,756 / 4,176,062 data bytes;
|
||||
- Halo category: 494,589 / 1,770,166 code bytes and 4,017 / 7,574 functions;
|
||||
- tooling tests: 179/179 passed;
|
||||
- `git diff --check`: clean.
|
||||
|
||||
The fail-closed admission audit reports zero completion candidates and zero
|
||||
revocations. Its sole contradiction is the already-known
|
||||
`source/shell/shell_xbox` completion label, whose `_main` false positive is
|
||||
independently rejected by existing semantic policy; this wave neither touches
|
||||
nor changes it. No push is performed.
|
||||
-109
@@ -1,109 +0,0 @@
|
||||
# `action_charge.obj` Jonas public residual recovery — 2026-08-28
|
||||
|
||||
## Result
|
||||
|
||||
This bounded recovery starts from cumulative integration commit
|
||||
`9c006fff3ae73abaa3d83ca208aa20ab90785163` and the existing 15/22 exact
|
||||
partial. It recovers the two remaining public functions previously proven by
|
||||
the archived full-TU experiment:
|
||||
|
||||
| Function | Padded bytes | Relocations | Normalized SHA-256 |
|
||||
| --- | ---: | ---: | --- |
|
||||
| `_action_charge_control` | 544 | 6 | `5be694b750701983145a5c29336fe5dc3ffe97cd7b53111013694012215e2095` |
|
||||
| `_action_charge_is_leaping` | 80 | 3 | `9ddd3d1296e581d078e6958f4039f9bde736698282368436b60d130978e7b275` |
|
||||
| **Wave gain** | **624** | **9** | |
|
||||
|
||||
All fifteen inherited functions remain strict exact. `action_charge.obj`
|
||||
advances from 15/22 and 720/6,176 padded bytes to 17/22 and 1,344/6,176 padded
|
||||
bytes. It remains `NonMatching`.
|
||||
|
||||
The retained source Git blob is
|
||||
`7a87fe26032376f229e251ab6cf0f2f7f6f945da`. The January split-object
|
||||
SHA-256 is `76c4c0b62850ffaa42fe5027c3e68b2cc42f7640c1156342c9a9cc4d1125afea`.
|
||||
|
||||
## Provenance and scope
|
||||
|
||||
Every current action-charge ledger and the archived frontier ledger at commit
|
||||
`677defb9d9b4dd0ac4f20bc2c5dbd53bf3e8d7f5`, ledger blob
|
||||
`bbb630a9fc673dab443948add44b8457e3b465e4`, was read before emission. That
|
||||
archived full-TU experiment independently measured both retained source shapes
|
||||
strict exact, then restored its production source because
|
||||
`action_charge_perform` and `action_charge_setup` remained non-exact. The
|
||||
current pre-wave source blob was
|
||||
`64818f49f816817883be1621a9737166c7615bb7`.
|
||||
|
||||
The readable semantic oracle is HCEA commit
|
||||
`570c83fd9c365dad6f2a3e7041705d5b84c7847c`:
|
||||
|
||||
- `src/blam/ai/action_charge_control.c`, blob
|
||||
`b29413ab09c0db5049d66b62cacf7e6d717c3149`, payload SHA-256
|
||||
`4fd1e1de0fbf920e95a2058ba55d8de27893a99981cfb8119178876970bd2451`;
|
||||
- `src/blam/ai/action_charge_is_leaping.c`, blob
|
||||
`38fc8c40afa3cc720f5d8f784c22da25150febcc`, payload SHA-256
|
||||
`c6857cdfcc0225c97dd8bdfe56a8f5a8ea721881a48ca58e71b8af0911b7a7d5`.
|
||||
|
||||
January COFF, current typed actor layouts, and existing exact-history evidence
|
||||
remain authoritative where the later donor evolved. The source uses
|
||||
`actor_get` and `actor_definition_get` rather than raw object casts. The only
|
||||
new header is the existing typed `game/game.h` interface for `game_time_get`;
|
||||
no shared declaration or storage owner changes.
|
||||
|
||||
`action_charge_control` restores the target's exact priority-local topology,
|
||||
including priority 5 initialized in the fallback block and priority 7 written
|
||||
only in the locked-aiming arm. It then applies typed crouch, leap, panic,
|
||||
movement, and combat orders through named actor fields. `action_charge_is_leaping`
|
||||
forms one typed charge-state pointer, keeps one shared result return, and tests
|
||||
the authenticated 30-tick leap window.
|
||||
|
||||
## Bounded five-body disposition
|
||||
|
||||
The historical frontier also proved three private/collision bodies exact:
|
||||
`_code_000010d0`, `_code_000023d0`, and `_collision_test_line`. They were
|
||||
included in the one natural recovery packet to test whether the current partial
|
||||
could own them without the two excluded large callers.
|
||||
|
||||
VC7 correctly eliminated all three because the current TU contains no lawful
|
||||
caller after `action_charge_perform` and `action_charge_setup` are omitted.
|
||||
They were therefore `UNWRITTEN`, not byte residuals. Their candidate bodies,
|
||||
prototypes, macro rename, constants, and include support were all pruned before
|
||||
the retained replay. No synthetic caller, anchor, forced emission, external
|
||||
ownership rewrite, or zero-credit support body is retained.
|
||||
|
||||
The archived ledger already proves the two large residuals are structural:
|
||||
|
||||
- `_action_charge_perform` is 3,248 padded bytes with the exact size, frame,
|
||||
relocation count, and destination sequence but a recovered source topology
|
||||
that moves 82 of 84 relocation addresses;
|
||||
- `_action_charge_setup` is 944 padded bytes and needs the original shared-exit
|
||||
CFG rather than another early-return or `goto` spelling.
|
||||
|
||||
Do not retry those fixed points without authentic debug-scope/source topology.
|
||||
Reopen the three dead helpers only when an admissible authentic caller causes
|
||||
ordinary target-compatible materialization.
|
||||
|
||||
## Policy and validation
|
||||
|
||||
The retained code is typed readable C. Each parameter occupies its own line;
|
||||
both functions end in explicit returns. It contains no assembly, `volatile`,
|
||||
`register`, pragma, intrinsic, optimizer barrier, raw address or byte-offset
|
||||
access, pointer/integer reconstruction, punning, inactive-union access,
|
||||
undefined behavior, synthetic retention, object-byte forcing, comparator
|
||||
exception, configuration edit, or compiler-flag change.
|
||||
|
||||
The isolated retained-only `/Zs` parse and normal XDK 3911 replay passed. Direct
|
||||
strict comparison returned `all_equal: true` for every one of the 17 emitted
|
||||
target functions. After copying the identical source blob to cumulative
|
||||
integration, one normal Ninja edge rebuilt
|
||||
`build/base/source/ai/action_charge.obj` and
|
||||
`python tools/campaign/gate.py source/ai/action_charge --all` reported:
|
||||
|
||||
```text
|
||||
exact 17 residual 0 unwritten 5
|
||||
```
|
||||
|
||||
The five unwritten target functions are exactly the two documented large
|
||||
fixed points and the three pruned dead helpers. `git diff --check` is clean.
|
||||
Only `source/ai/action_charge.c` and this Jonas-owned ledger are added by this
|
||||
wave. Units, Vehicles, Claude-active source, shared headers, configuration,
|
||||
semantic policy, parked records, comparator code, and object status labels are
|
||||
untouched.
|
||||
@@ -1,243 +0,0 @@
|
||||
# `action_charge.obj` Jonas real-random recovery
|
||||
|
||||
## Result
|
||||
|
||||
This bounded recovery starts from cumulative commit
|
||||
`c07cbfb90b8bf67a86cb28bc6f3a1dffed70a486`. It adds the ordinary typed
|
||||
`real_random` wrapper already authenticated by January COFF, the canonical
|
||||
math interface, and the archived full-TU action-charge experiment.
|
||||
|
||||
`_real_random` is strict exact on the frozen recovery compile. The two
|
||||
inherited lifecycle leaves remain strict exact, so `action_charge.obj`
|
||||
advances from 2/22 to 3/22 exact functions. It remains `NonMatching` and
|
||||
receives no data credit.
|
||||
|
||||
| Function | Meaningful / padded | Relocs | Normalized SHA-256 | Disposition |
|
||||
| --- | ---: | ---: | --- | --- |
|
||||
| `_real_random` | `13 / 16` | 2 | `50eeeb3dc58069325659d8bc0b6f2c17bb9f4fdce278b2f1a37edb64f4fcc60c` | newly exact |
|
||||
| `_action_charge_begin` | `80 / 80` | 3 | `c78c6feeb10fda8857834f5264614aa976498059590ee08304aef25f21af8bf3` | inherited exact |
|
||||
| `_action_charge_update` | `71 / 80` | 2 | `f2591b2de350c20aefef42c38623875dca494bb46a51d06c6dcd5947b035976e` | inherited exact |
|
||||
|
||||
The accepted object total is 164 meaningful bytes, 176 padded bytes, and
|
||||
seven relocations across three functions.
|
||||
|
||||
## Provenance and recovery status
|
||||
|
||||
This is not represented as a compiler-naive first shot. Archived commit
|
||||
`677defb9d9b4dd0ac4f20bc2c5dbd53bf3e8d7f5` records a 20/22 full-TU
|
||||
experiment in `docs/object_matching_logs/action_charge_obj.md`, blob
|
||||
`bbb630a9fc673dab443948add44b8457e3b465e4`. That experiment independently
|
||||
compiled `_real_random` strict exact, then restored the translation unit
|
||||
because the large `action_charge_perform` and `action_charge_setup` bodies
|
||||
remained non-exact. This wave recovers only the already authenticated wrapper;
|
||||
none of the rejected large-function source, scheduling hypotheses, or
|
||||
temporary data owners is reused.
|
||||
|
||||
The current two-leaf checkpoint is blob
|
||||
`0ab1bc6655eda440815fd2c185160f8ba96de081`, last clarified by commit
|
||||
`4053598caa60b40da0e660c138708f85e2a8550b`. The baseline source blob is
|
||||
`d34d932679150399937475d915ade404f7f94ac9`; the frozen recovery source blob is
|
||||
`3e76470cf8be066072239845cbf08e37aeffa458`.
|
||||
|
||||
The January split object has SHA-256
|
||||
`76c4c0b62850ffaa42fe5027c3e68b2cc42f7640c1156342c9a9cc4d1125afea`.
|
||||
The compiler is Microsoft 32-bit C/C++ Optimizing Compiler `13.00.9254.1`,
|
||||
SHA-256
|
||||
`483e00c47bb08d699475a642bcff15b5b2036350b31c540e88a506baf101da11`,
|
||||
with the unchanged XDK 3911 C command and flags.
|
||||
|
||||
## Typed interface and source shape
|
||||
|
||||
Current `source/math/real_math.h`, blob
|
||||
`f14567675126171a4b1c2d3052e8058c68c029c2`, declares both callees and owns
|
||||
the canonical inline behavior:
|
||||
|
||||
```c
|
||||
real real_random(
|
||||
void)
|
||||
{
|
||||
return real_seed_random(
|
||||
get_global_random_seed_address());
|
||||
}
|
||||
```
|
||||
|
||||
`actions.h` is the first transitive route to `real_math.h` in this TU. The
|
||||
inline name is therefore narrowly macro-renamed to `real_random_inline` after
|
||||
`cseries.h` and before `actions.h`, then undefined after the existing include
|
||||
list. The explicit external definition above is retained in the public-code
|
||||
section. No shared-header declaration, duplicate prototype, synthetic caller,
|
||||
or emission anchor is introduced. Direct symbol inspection proves that no
|
||||
`_real_random_inline` owner or reference is emitted.
|
||||
|
||||
Both dependencies are strict exact in complete
|
||||
`source/math/random_math.obj`:
|
||||
|
||||
- `_get_global_random_seed_address`: 53 meaningful / 64 padded bytes, seven
|
||||
relocations, normalized SHA-256
|
||||
`978f6fa37835b338c2088717e09aa32a8e80f074c0c52043c3ee74f9e0c3e9a1`;
|
||||
- `_real_seed_random`: 48 meaningful / 48 padded bytes, two relocations,
|
||||
normalized SHA-256
|
||||
`ad693d3107104928cec2113aa91e03214c37eced08553a417d7f90191ccec3b4`.
|
||||
|
||||
## Strict relocation and ownership evidence
|
||||
|
||||
The target and candidate padded bytes are identical. Both relocations are
|
||||
zero-addend REL32 entries:
|
||||
|
||||
| Offset | Destination |
|
||||
| ---: | --- |
|
||||
| `+0x01` | `_get_global_random_seed_address` |
|
||||
| `+0x07` | `_real_seed_random` |
|
||||
|
||||
The target-authoritative census is 3/22 strict-exact functions against 6,032
|
||||
meaningful / 6,176 padded target code bytes. The candidate adds exactly one
|
||||
NODUPLICATES code COMDAT owner `_real_random`, plus undefined references to
|
||||
the two typed callees and VC7's ordinary compiler-generated `__fltused`
|
||||
linker marker. The latter is an undefined external, not a runtime owner; the
|
||||
same natural marker is present in the accepted `action_alert.obj` real wrapper.
|
||||
There is no owner removal and no candidate `.rdata`, `.data`, BSS, COMMON, or
|
||||
other runtime non-code section. All fifteen target read-only COMDATs, 243 raw
|
||||
payload bytes / 256 progress bytes, remain uncredited.
|
||||
|
||||
The generic baseline regression gate reports exactly `_real_random` as
|
||||
`NEWLY_EXACT`, both lifecycle functions as `still_exact`, and
|
||||
`changed_nonexact: []`. Its nonzero result is confined to the expected new
|
||||
symbol set plus compiler debug changes in `.debug$F` and `.debug$S`; no
|
||||
adjudication or comparator exception is added.
|
||||
|
||||
## Compile and policy record
|
||||
|
||||
The frozen source passed the XDK `/Zs` parse-only check. The subsequent Ninja
|
||||
dry run exposed exactly one
|
||||
`CL build\base\source\ai\action_charge.obj` edge. That edge was invoked once,
|
||||
reported exactly `[1/1] CL build\base\source\ai\action_charge.obj`, and its
|
||||
output was immediately preserved as
|
||||
`build/audit/action_charge_real_random_recovery_20260826.obj`, 1,405 bytes,
|
||||
raw SHA-256
|
||||
`365281ea87d2f74746742f68b8928223b05bee7abe16d5207734e761ba02ebb5`.
|
||||
No source spelling, include position, declaration, retry, scheduling tune,
|
||||
compiler flag, or second candidate compile followed.
|
||||
|
||||
The retained source is readable typed C with `void` on its own parameter line
|
||||
and a direct explicit return. It contains no assembly, `volatile`, `register`,
|
||||
pragma, intrinsic, attribute, forced inlining, barrier, raw offset or address,
|
||||
pointer/integer reconstruction, cast or union pun, inactive-union access,
|
||||
undefined behavior, synthetic caller or anchor, object-byte patch, comparator
|
||||
exception, or alternate compiler flag.
|
||||
|
||||
Direct hardened comparison reports `all_equal: true` for the new wrapper and
|
||||
both sentinels. The target object dry run reports no work after preservation,
|
||||
`git diff --check` and the changed-path/protected-file review pass, and all 179
|
||||
tooling tests pass. Whole-campaign reports and complete Halo/libcmt validation
|
||||
are deferred to the corrected cumulative-HEAD closure so this isolated
|
||||
worktree does not rebuild unrelated historical outputs.
|
||||
|
||||
Only `source/ai/action_charge.c` and this Jonas-owned ledger are changed. The
|
||||
approval-gated Units package and its protected neighbors remain frozen. No
|
||||
push is performed.
|
||||
|
||||
## Committed-state replay
|
||||
|
||||
Implementation-and-ledger commit
|
||||
`8ed01222d5e1eec38b3a7a8801c05e52926c753e` was clean before replay. Its
|
||||
committed source blob remains
|
||||
`3e76470cf8be066072239845cbf08e37aeffa458`. The clean selected-unit manifest
|
||||
is `build/audit/action_charge_real_random_committed_20260826.json`, 250,738
|
||||
bytes, SHA-256
|
||||
`0fa2c07f0859a868f37e10c0ae0f6094d02a265d26522a00d8f025eaf90945ac`.
|
||||
|
||||
The resolved generated object path was verified to remain inside the isolated
|
||||
worktree. `build/base/source/ai/action_charge.obj` was literally deleted, its
|
||||
absence was confirmed, the Ninja dry run exposed exactly one expected compiler
|
||||
edge, and the normal rebuild reported exactly
|
||||
`[1/1] CL build\base\source\ai\action_charge.obj`. The preserved committed
|
||||
replay is 1,405 bytes with raw SHA-256
|
||||
`97d6ffb9f5f320010affd46b659c0de3a2012be0a8376e2e8c9b6697fb9e696f`.
|
||||
|
||||
The replay and frozen recovery objects have identical length and differ at
|
||||
exactly COFF header offsets `+0x4` and `+0x5`, compile-timestamp bytes. Every
|
||||
modeled section, symbol, meaningful and padded byte, and relocation is
|
||||
identical. Direct hardened comparison again reports `all_equal: true` for all
|
||||
three accepted functions. The committed manifest check has no failures or
|
||||
warnings, no newly exact or changed-nonexact entry, and places
|
||||
`_action_charge_begin`, `_action_charge_update`, and `_real_random` in
|
||||
`still_exact`. Both the selected object dry run and normal invocation report
|
||||
no work afterward.
|
||||
|
||||
This section is the only tracked post-implementation change. No push is
|
||||
performed.
|
||||
|
||||
## Corrected cumulative-HEAD closure
|
||||
|
||||
The cumulative branch was fast-forwarded from
|
||||
`c07cbfb90b8bf67a86cb28bc6f3a1dffed70a486` through the isolated
|
||||
implementation and replay-ledger commits to
|
||||
`450249b0ead2989462f6e7d1218f0ad9ebd0a7d6`. The implementation source blob
|
||||
remains `3e76470cf8be066072239845cbf08e37aeffa458`; no protected source, shared
|
||||
header, storage declaration, configuration, semantic ledger, parked manifest,
|
||||
or object-status file changed during integration.
|
||||
|
||||
From that clean corrected HEAD, the resolved cumulative
|
||||
`build/base/source/ai/action_charge.obj` was verified inside the cumulative
|
||||
worktree and literally deleted. The Ninja dry run exposed exactly one expected
|
||||
compiler edge, and the normal rebuild reported exactly
|
||||
`[1/1] CL build\base\source\ai\action_charge.obj`. The preserved corrected
|
||||
replay is
|
||||
`build/audit/action_charge_real_random_corrected_head_replay_20260826.obj`,
|
||||
1,393 bytes, raw SHA-256
|
||||
`f78c30bbff7d78d9b9f576a4b36a1bd5831ef8ba54e1f373b3ebf9102477cb13`.
|
||||
|
||||
Direct hardened comparison again reports `all_equal: true` for
|
||||
`_real_random`, `_action_charge_begin`, and `_action_charge_update`. The
|
||||
accepted corrected delta remains exactly one function, 13 meaningful bytes,
|
||||
16 padded bytes, and two relocations, with no changed non-exact function and
|
||||
no runtime-data gain or regression.
|
||||
|
||||
The isolated and cumulative raw objects are root- and timestamp-sensitive.
|
||||
VC7's `.debug$S` record embeds the absolute output-object path: it is 194
|
||||
bytes in the isolated `action-charge-three-leaf-20260821` worktree and 182
|
||||
bytes in `units-integration-20260824`, exactly accounting for the twelve-byte
|
||||
object-size difference. After report regeneration, the cross-worktree
|
||||
manifest check reports only this `.debug$S` difference. All three accepted
|
||||
functions are `still_exact`, `changed_nonexact` is empty, and every modeled
|
||||
production code and runtime non-code record is stable.
|
||||
|
||||
The corrected clean manifest is
|
||||
`build/audit/action_charge_real_random_corrected_head_manifest_20260826.json`,
|
||||
250,738 bytes, SHA-256
|
||||
`a5a9efe588d81de5e8dce55df5a44cbe4627dc0c09500e67f9df4db6da0a616e`.
|
||||
Its no-build self-check has no failures or warnings, no newly exact or changed
|
||||
non-exact entries, and retains all three functions in `still_exact`.
|
||||
|
||||
Regenerated corrected artifacts are:
|
||||
|
||||
- `action_charge_real_random_corrected_head_report_20260826.json`: 1,573,815
|
||||
bytes, SHA-256
|
||||
`4ccad6c2d5fd4d48c0e4755d3dd07fddac6a800d15b41620bc01667440b4d6fe`;
|
||||
- `action_charge_real_random_corrected_head_semantic_20260826.json`: 2,972,764
|
||||
bytes, SHA-256
|
||||
`2408321ac6feeab0c9b2ff8de676fd408d3cdb369419ec3afcd7e896f6590a9d`;
|
||||
- `action_charge_real_random_corrected_head_admission_20260826.json`: 384
|
||||
bytes, SHA-256
|
||||
`f0aa45c22cc604fb74abc388b06dd79a27e7a0b498a5d28837a9e785680c9a36`;
|
||||
- `action_charge_real_random_corrected_head_parked_20260826.json`: 3,950
|
||||
bytes, SHA-256
|
||||
`cfac03aea5be607c19a6a40bcdbc1164e71ffb0179602af4bd37b3fd50e26d1d`.
|
||||
|
||||
The hardened semantic audit evaluates 4,246 functions, accepts 4,165 exact
|
||||
functions, and reports zero unit errors. Campaign progress is 375/833 objects,
|
||||
4,139/11,060 exact functions, 502,200/2,198,102 meaningful code bytes, and
|
||||
1,835,088/4,176,062 matched data bytes. Halo progress is 273/468 objects,
|
||||
3,972/7,574 exact functions, 489,286/1,770,166 meaningful code bytes, and
|
||||
1,829,896/3,923,451 matched data bytes. `action_charge.obj` is 3/22 exact with
|
||||
164 meaningful exact code bytes and no data credit.
|
||||
|
||||
Admission remains zero candidates and zero revocations; only the inherited
|
||||
`source/shell/shell_xbox` completion-label contradiction remains. Parks remain
|
||||
three active / zero stale / zero invalid. The selected object and complete
|
||||
Halo/libcmt dry runs and normal invocations all report no work, and all 179
|
||||
tooling tests pass.
|
||||
|
||||
The approval-gated Units package remains frozen. This closure does not
|
||||
constitute its required exact approval phrase and authorizes no edit to Units
|
||||
or its protected neighbors. No push is performed.
|
||||
@@ -1,165 +0,0 @@
|
||||
# `action_charge.obj` Jonas two-leaf wave
|
||||
|
||||
## Result
|
||||
|
||||
This bounded source-only wave starts from authoritative integration commit
|
||||
`3f2ba63dfb1258f7e36baaec69fe495bcefdc20f`. The three permitted public
|
||||
action-charge leaves were emitted together in exactly one natural candidate
|
||||
compile. `_action_charge_begin` and `_action_charge_update` were independently
|
||||
strict and are retained. `_action_charge_is_leaping` missed and was removed
|
||||
immediately, without a spelling, declaration, control-flow, or compiler-control
|
||||
retry.
|
||||
|
||||
`action_charge.obj` advances from 0/22 to 2/22 exact functions and remains
|
||||
`NonMatching`.
|
||||
|
||||
| Retained function | Meaningful | Padded | Relocations | Normalized SHA-256 |
|
||||
| --- | ---: | ---: | ---: | --- |
|
||||
| `_action_charge_begin` | 80 | 80 | 3 | `c78c6feeb10fda8857834f5264614aa976498059590ee08304aef25f21af8bf3` |
|
||||
| `_action_charge_update` | 71 | 80 | 2 | `f2591b2de350c20aefef42c38623875dca494bb46a51d06c6dcd5947b035976e` |
|
||||
| **Wave gain** | **151** | **160** | **5** | |
|
||||
|
||||
The hardened COFF comparator proves identical padded bytes and exact
|
||||
relocation addresses, types, destinations, and addends. The target owns 6,032
|
||||
meaningful code bytes in 22 functions and 6,176 padded code bytes. Its fifteen
|
||||
non-code COMDATs contain 243 payload bytes (256 bytes in the progress metric);
|
||||
all remain outside this wave's credit. The final candidate owns no runtime
|
||||
non-code data or storage: it emits no `.rdata`, `.data`, `.bss`, or COMMON
|
||||
symbol.
|
||||
|
||||
## Provenance and ABI
|
||||
|
||||
- Baseline `source/ai/action_charge.c` blob:
|
||||
`4a2578245ccc649a0a6c20823cfb8f204cc201e6`.
|
||||
- Retained source blob/payload SHA-256:
|
||||
`d34d932679150399937475d915ade404f7f94ac9` /
|
||||
`78f7439e940d38166d075c19804f74524e0cb784199c533ab97a8c7b785e9bb4`.
|
||||
- January executable SHA-256:
|
||||
`4cc87b45f721270392a96f1674ed2b5cd4a7bb4355faeab4531d1cf1884d9520`.
|
||||
- January split-object SHA-256:
|
||||
`76c4c0b62850ffaa42fe5027c3e68b2cc42f7640c1156342c9a9cc4d1125afea`.
|
||||
- Clean HCEA semantic donor commit:
|
||||
`c168af2e747d3095d9a29418ae401f3a39544863`. Its
|
||||
`src/action_charge_begin.c`, `src/action_charge_update.c`, and
|
||||
`src/action_charge_is_leaping.c` blobs are respectively
|
||||
`6692a82a1ba231cc7d91c38860096cf6ec80a8e4`,
|
||||
`3e7d6333d32d89108bfa8b6db76390512094044b`, and
|
||||
`38fc8c40afa3cc720f5d8f784c22da25150febcc`. Their payload SHA-256 values
|
||||
are respectively
|
||||
`9cdc2a06b44a3a69e3418bf79e2aced52111cbd5d9ab9404044c9b472de185c7`,
|
||||
`a949c7b6fb3ebbd1db455d09f6b0856788d05aa52ce52e0eba3a7b801d1474bd`,
|
||||
and
|
||||
`c6857cdfcc0225c97dd8bdfe56a8f5a8ea721881a48ca58e71b8af0911b7a7d5`.
|
||||
These files supply independently readable behavior, not target-derived
|
||||
emission anchors.
|
||||
- Cross-build correspondence commit
|
||||
`8ffdbab2301d17215b6f4b4a109f0e0a6f09b53d`, blob
|
||||
`ec76e6464bf79d444779720d5efb9432bf5378d7`, classifies all three names as
|
||||
exact-unique, ordinary `cdecl`, one-parameter functions. January COFF and
|
||||
callers remain authoritative for the 32-bit parameter type.
|
||||
- The existing `struct action_specification` types `begin` and `update` as
|
||||
`void (*)(long)`. January's action table relocates to the two functions at
|
||||
`+580` and `+588`. Existing `actions.h` types `action_charge_is_leaping` as
|
||||
`boolean(long)`, and January `_actor_is_leaping` calls it at relocation
|
||||
`+33`.
|
||||
- The earlier evidence-only frontier commit
|
||||
`677defb9d9b4dd0ac4f20bc2c5dbd53bf3e8d7f5`, ledger blob
|
||||
`bbb630a9fc673dab443948add44b8457e3b465e4`, independently records all three
|
||||
public leaves as exact on their first complete readable shapes. It is not a
|
||||
production-source donor and none of its tuned control/private-helper forms
|
||||
were reused.
|
||||
- Compiler: Microsoft 32-bit C/C++ Optimizing Compiler `13.00.9254.1` for
|
||||
80x86, SHA-256
|
||||
`483e00c47bb08d699475a642bcff15b5b2036350b31c540e88a506baf101da11`,
|
||||
with the repository's unchanged XDK 3911 command and flags.
|
||||
|
||||
The retained signatures are:
|
||||
|
||||
```c
|
||||
void action_charge_begin(
|
||||
long actor_index);
|
||||
void action_charge_update(
|
||||
long actor_index);
|
||||
```
|
||||
|
||||
Existing `actions.h`, `actors.h`, and `actor_definitions.h` own the action,
|
||||
actor, charge-state, and firing-variant layouts. The callee's return/argument
|
||||
types are corroborated by existing source TUs, so the missing declaration is
|
||||
kept translation-unit-local. The firing-situation enumerator is likewise
|
||||
source-local because no shared header presently owns it. No shared-header or
|
||||
storage repair is needed.
|
||||
|
||||
## Authenticated behavior and one-shot rejection record
|
||||
|
||||
`action_charge_begin` resolves the full 32-bit actor handle through
|
||||
`actor_get`. For vehicle-strafing charge with the matching firing-variant
|
||||
special-fire situation, it decrements a positive signed-short deny-attempt
|
||||
counter. Its target relocations are `DIR32 _actor_data` at `+4`,
|
||||
`REL32 _datum_get` at `+16`, and
|
||||
`REL32 _actor_combat_get_firing_variant_definition` at `+37`.
|
||||
|
||||
`action_charge_update` resolves the same typed actor handle. During a launched
|
||||
melee leap, before a melee attack and after the actor is no longer midair, it
|
||||
increments the signed-short leap-failure timer. Its target relocations are
|
||||
`DIR32 _actor_data` at `+8` and `REL32 _datum_get` at `+15`.
|
||||
|
||||
All three public candidates were compiled together once. The rejected
|
||||
`_action_charge_is_leaping` target is 66 meaningful/80 padded bytes with three
|
||||
relocations and normalized SHA-256
|
||||
`9ddd3d1296e581d078e6958f4039f9bde736698282368436b60d130978e7b275`.
|
||||
The first natural candidate was also an 80-byte, three-relocation COMDAT, but
|
||||
its normalized SHA-256 was
|
||||
`56aa0e8827a4ebecba9e4310f944bc24c07ffb5c2b2e39ef46ea11ad36899f31`.
|
||||
The target forms one charge-state pointer and shares its epilogue; the readable
|
||||
HCEA early-return shape instead accesses full actor offsets and duplicates the
|
||||
return. Consequently the common `game_time_get` relocation occurs at target
|
||||
`+48` but candidate `+46`. The candidate COMDAT and its support-only prototype
|
||||
were removed without retry. The one-shot three-body candidate object SHA-256
|
||||
was `3ee981a618bc3f891786bc839c2c51a3bd11bfb9a16a1e90f382d0569fe3a8af`.
|
||||
|
||||
`action_charge_control`, `action_charge_perform`, `action_charge_setup`, both
|
||||
anonymous `code_` helpers, generic helper emissions, and every data/storage
|
||||
section were explicitly outside scope and are absent from the final object.
|
||||
|
||||
## Policy, scope, and validation
|
||||
|
||||
Only `source/ai/action_charge.c` and this new Jonas-owned ledger are changed.
|
||||
No shared header, storage definition, data section, configuration, semantic
|
||||
exception, parked record, completion label, protected-five source,
|
||||
pre-existing Markdown, or Claude-owned file is edited.
|
||||
|
||||
The retained source is readable typed C. The guarded decrement remains in the
|
||||
positive signed-short range. The timer increment is promoted to 32-bit `int`,
|
||||
so its arithmetic cannot overflow; a hypothetical value above `SHRT_MAX`
|
||||
narrows according to the implementation-defined two's-complement behavior of
|
||||
the authenticated VC7/Xbox target. That ordinary target contract is already
|
||||
used by the project's signed-short AI timers and is not undefined behavior or
|
||||
an emission control. The source contains no assembly, raw address or
|
||||
byte-offset dereference, pointer/integer reconstruction, pointer or union pun,
|
||||
inactive-union access, undefined overflow, volatile scheduling device,
|
||||
force-inline annotation, optimizer pragma/barrier, synthetic anchor, or
|
||||
object-byte forcing.
|
||||
|
||||
- Forced rebuild of the final retained source: pass. The only defined code
|
||||
symbols are `_action_charge_begin` and `_action_charge_update`; there is no
|
||||
runtime `.rdata`, `.data`, `.bss`, or COMMON ownership. Direct hardened
|
||||
comparison passes both functions.
|
||||
- Complete `halobetacache_build` and `libcmt_build`: pass (568 remaining edges
|
||||
after the final translation unit's forced rebuild).
|
||||
- Semantic audit: 470 units, 4,074 functions evaluated, 3,934 semantic exact,
|
||||
101 hidden exact / 61,876 hidden code bytes, 3,995 accepted exact, and zero
|
||||
unit errors.
|
||||
- Campaign progress: 375/833 complete objects, 3,982/11,060 exact functions,
|
||||
476,846/2,198,102 meaningful code bytes, and
|
||||
1,835,088/4,176,062 matched data bytes. This wave adds two functions and 151
|
||||
meaningful bytes with no data increase.
|
||||
- Admission audit: zero candidates and zero revocations; only the inherited
|
||||
`source/shell/shell_xbox` completion-label contradiction remains.
|
||||
- Parked validation: three active, zero stale, and zero invalid entries.
|
||||
- Complete tooling suite: 179/179 tests pass; `git diff --check` is clean.
|
||||
|
||||
A clean committed-state regression snapshot/check followed by deletion and
|
||||
forced rebuilding of `action_charge.obj` is the final same-path reproducibility
|
||||
proof. The post-rebuild hardened comparison must remain strict for both
|
||||
accepted functions, and the rejected symbol must remain absent. No push is
|
||||
performed.
|
||||
@@ -1,120 +0,0 @@
|
||||
# `action_charge.obj`: setup frame lever and helper-linkage measurement (Opus 5 150K house-clean lane, wave w2, 2026-09-14)
|
||||
|
||||
## Result
|
||||
|
||||
- `_action_charge_setup` (944 padded, previously a structurally incomplete 688 / 20 residual) is now a complete typed-C body,
|
||||
landed as **fuzzy** (zero credit): **944 / 29 relocations, instruction-identical to January except the placement of one
|
||||
`result = FALSE` store** (`mov byte [ebp-1],0` at +0x138 instead of +0xe4).
|
||||
- A **strict-EXACT** setup candidate exists (`scratch/workers/action_charge/w2/v3.c`, 21/22 object). It is held back because it
|
||||
needs a January-proven redundant `result = FALSE;` store (see section 4). Owner ruling requested.
|
||||
- `_action_charge_perform` is unchanged (fuzzy 3216 / 84). The requested helper-linkage measurement is recorded in section 5; the
|
||||
ruling alone does not produce an exact function.
|
||||
- Object: `== exact 20 residual 2 unwritten 0` (baseline identical counts). No newly exact function. All 20 baseline-exact rows
|
||||
keep their listings row for row.
|
||||
|
||||
## 1. Baseline and provenance
|
||||
|
||||
- Worktree `C:\halo-worktrees\opus5-150k-house-clean-20260914`, base `ea9175577`. Gate without the `_point_from_line3d` guard
|
||||
(brief 3b: action_charge.obj is the genuine owner; the final object defines exactly one `_point_from_line3d`, strict EXACT,
|
||||
sha16 `9b763841f8519177`).
|
||||
- Baseline rows: perform `[size 3216!=3248, sha]`, setup `[size 688!=944, relocs 20!=29, sha]`, 20 EXACT.
|
||||
- Read: all eight earlier action_charge ledgers, the 100K handoff, the fresh-graphs worker notes and scratch
|
||||
(`opus5-30k-fresh-graphs-20260914/scratch/workers/action_charge`: `setup_v12.txt`, `t_setup.asm`, `t_perform.asm`).
|
||||
`branch_sweep`: 12 blobs, none better. A cut-off earlier run in this lane left undocumented probes
|
||||
(`scratch/workers/action_charge/d_*.c`, `probe/`); used as evidence only.
|
||||
|
||||
## 2. New evidence
|
||||
|
||||
- **HCEX.pdb (SHIP) locals** (`DIA2Dump -sym`): `action_charge_setup` homes only `short melee_start_tick`,
|
||||
`short melee_end_tick`, `float melee_start_range`, `float melee_end_range` (all other locals enregistered).
|
||||
`action_charge_valid_melee_destination` is `static unsigned char (long actor_index, short goal, union real_point3d *melee_target_point)`
|
||||
with locals `estimated_position`, `collision`. Later build: names and signature shape only.
|
||||
- **January caller bytes** confirm that signature: setup pushes `[ebp+0xc]` (the short `goal` parameter) and passes
|
||||
`&prop->center_of_mass` in ESI. The 2026-09-06 ledger's "the point is the second argument, do not import the short
|
||||
signature" premise is refuted by these bytes; the helper ignores the stack `goal`, and its point parameter is
|
||||
`melee_target_point`. The helper stays strict EXACT with the authentic signature, and the `(void)melee_target_point;` line is gone.
|
||||
- `ai_debug.c` charge-decision renderer: `field_198` is the "airborne" (leap) flag, `field_194` is the cannot-move range.
|
||||
|
||||
## 3. Setup frame lever (new measured VC7 13.00.9254 law)
|
||||
|
||||
January's frame is 0x20 with `leap` (byte) at [-8] and `end_tick` (short) at [-6] in **one** 4-byte cell. The v12 body declares
|
||||
`leap` and the four tick/range outputs in the same block and gets 0x24 (separate cells). Wrapping the four outputs in a nested
|
||||
block around the `unit_get_melee_range_and_ticks` if/else (leap stays in the enclosing block) reproduces January's frame and
|
||||
slot set exactly.
|
||||
|
||||
Law: locals declared in the **same** block never share a frame cell. A nested-block local can be packed into, or overlap, an
|
||||
enclosing local's cell when their live ranges allow it. Probe `scratch/workers/action_charge/probe2/b.c`: f1 (same scope)
|
||||
frame 20, f2/f3/f4 (outputs nested) frame 16. This contradicts the older note that flattening a block is inert. Only
|
||||
promotion to the enclosing scope was measured there.
|
||||
|
||||
## 4. Setup: the redundant-store blocker
|
||||
|
||||
January stores 0 to `result` ([ebp-1]) at +0xe4, which dominates the inhibited test, and again at +0xea (inhibited arm) and
|
||||
+0x107 (notarget arm). The deep failure arms (no-animation, cannot-move) have no store. Only the literal source
|
||||
`result = FALSE;` before `if (TEST_FLAG(... inhibited))`, together with `result = FALSE;` in both arms, is strict EXACT
|
||||
(`w2/setup_exact.txt`).
|
||||
|
||||
Non-redundant alternatives measured (all on the nested-scope base):
|
||||
|
||||
| Shape | Size / relocs | Outcome |
|
||||
| --- | --- | --- |
|
||||
| A1 pre-branch store only | 1024 | tail-duplicated epilogues |
|
||||
| A4 store at top of melee arm | 1024 | same |
|
||||
| A6 stores in every failure arm, none before | 1056 | `result` loses its home |
|
||||
| R1 / R1b / R2 / R3 early `state_data->goal = goal; return ...;` arms | 1024 / 992 / 1024 / 1024 | own epilogues; VC7 does not coalesce return values into `result` |
|
||||
| **H1** arm stores + `result = FALSE;` first in the melee-attempt arm | **944 / 29** | one store placement differs (**landed, fuzzy**) |
|
||||
| H3 same store before `prop_get` | 928 | |
|
||||
| S2a / S5 separate valid/success flag copied into `result` | 1072 / 1072 | |
|
||||
|
||||
Owner ruling requested: admit the January-proven redundant store (`w2/v3.c`, the landed file with one `result = FALSE;` moved to
|
||||
before the inhibited test) for +944 padded exact. The class is the handoff's "January-proven redundant logic"
|
||||
(`_extract_sequence`).
|
||||
|
||||
## 5. Perform: helper-linkage measurement
|
||||
|
||||
`w2/v4_inline.c` is the landed file with `__inline` added to the 11 local helper definitions. January's atlas `i` records mark
|
||||
`normalize2d`, `point_from_line3d`, `magnitude3d`, `normalize3d` and `collision_test_line` as inline COMDATs.
|
||||
|
||||
- All 20 other rows stay strict EXACT, with no new owner.
|
||||
- Perform goes from 3216 to 3264 padded (meaningful about 3250 against January's 3246).
|
||||
- The two separate `direction = prop->actor_to_prop` copies come back.
|
||||
|
||||
What remains after the lever:
|
||||
|
||||
- one extra `mov ecx,[ebp-8]` prop reload at +0x256 (the only instruction-count difference);
|
||||
- the melee-abort block: January keeps `check_range` in BL and reloads the prop, with cells `check_range` [-2] and
|
||||
`berserk_ranges`+`melee` [-1]; ours keeps the prop in EBX;
|
||||
- the `&field_114` register;
|
||||
- x87 scheduling of `lead_fraction * ticks`, the suicide dot product and the ticks `movsx`;
|
||||
- argument registers of three calls.
|
||||
|
||||
Two more shapes were inert: W1 (the weapon pointer in its own block) and W3 (negated-or LOS test). Not landed:
|
||||
perform is an already-written residual and none of these is strict EXACT.
|
||||
|
||||
## 6. Checks (landed real file)
|
||||
|
||||
- `gate --all`: `exact 20 residual 2 unwritten 0`. The diff against HEAD's listing is only the setup row
|
||||
(`[size 688!=944, relocs 20!=29, sha]` becomes `[sha]`).
|
||||
- Parks: none for the unit.
|
||||
- Owner census against `build/base`: the only new owners are the target-owned `actor %s melee animation has no damage keyframe`
|
||||
string and the `state_data` assert literal, which January references as undefined. Pre-existing non-target owners
|
||||
(`_vector_from_points3d` SELECT_ANY, `__real@41f00000`, `__real@3f000000`, D3D tables) are unchanged.
|
||||
- `tools/fake_match_scan.py`: 0 leads.
|
||||
|
||||
## 7. Proposals
|
||||
|
||||
1. Owner ruling: admit `w2/v3.c` (redundant `result = FALSE;` proven by January +0xe4/+0xea/+0x107) as strict EXACT setup.
|
||||
2. Helper linkage (`__inline` local helper definitions): measured in section 5. It does not give exact credit on its own, so it is
|
||||
not needed now.
|
||||
3. Pre-existing debt, not introduced here: action_charge.c carries a consumer-local prototype of units.c's
|
||||
`unit_get_melee_range_and_ticks`. Its owner would be `source/units/units.h`, which has 66 includers
|
||||
(declaration-count risk, units.c protected neighbour). Proposed text, placed next to `unit_melee_attack_begin`:
|
||||
`boolean unit_get_melee_range_and_ticks(long unit_index, boolean secondary, short *melee_tick, real *attack_time, short *frame_count, real *damage_time);`
|
||||
in house one-parameter-per-line form.
|
||||
|
||||
## 8. Reopen criteria
|
||||
|
||||
- **setup:** the owner ruling above, or a non-redundant source that emits a dominating FALSE store before the inhibited branch
|
||||
while keeping both arm stores.
|
||||
- **perform:** a helper-linkage ruling plus a source-level cause for the +0x256 prop reload and the `check_range` BL allocation.
|
||||
Do not re-permute declaration order or scopes (fresh-graphs do-not-repeat list).
|
||||
@@ -1,188 +0,0 @@
|
||||
# `action_charge.obj`: setup store-position closure proof and perform linkage re-measurement (Opus 5 250K house-clean lane, wave w3c, 2026-09-15)
|
||||
|
||||
## Result
|
||||
|
||||
- **Nothing landed.** `git diff -- source/ai/action_charge.c` is empty; the object is unchanged at
|
||||
`== exact 20 residual 2 unwritten 0`, identical row for row to the baseline listing.
|
||||
- `_action_charge_setup` (944): re-measured at **291 instructions vs January's 291 with exactly ONE aligned
|
||||
difference** — the position of `mov byte ptr [ebp-1],0` (January `+0xe4`, ours `+0x138`). This wave adds a
|
||||
**construction proof that no non-redundant source spelling can place that store at `+0xe4`**, so the row is
|
||||
definitively owner-blocked on the laws_w3 A42 / R12 redundant-store ruling, not on a missing shape.
|
||||
- `_action_charge_perform` (3248): the `[size 3216!=3248]` gap is **fully attributed** to a single cross-jump —
|
||||
January emits the `direction = prop->actor_to_prop;` copy twice, ours once. The linkage lever was reproduced and
|
||||
a strictly better-motivated route for it was found (`p2.c`: delete the per-TU rename package and the 11 local
|
||||
helper bodies, take the helpers from `math/real_math.h`), producing **byte-identical** output to the previously
|
||||
declined `__inline` form. Neither reaches exact (3264), so neither is landable; the residual is 59 real
|
||||
allocation blocks.
|
||||
|
||||
## 1. Baseline and provenance
|
||||
|
||||
- Worktree `C:\halo-worktrees\opus5-150k-house-clean-20260914`, branch `opus/250k-house-clean-20260915`.
|
||||
- Gate WITHOUT the `_point_from_line3d` guard (brief 3b exception: this object is the genuine owner). The guard run
|
||||
fails only on that pre-existing owner: one code definition, 48 bytes, strict EXACT, sha16 `9b763841f8519177`.
|
||||
No additional candidate-only math owner exists (census below).
|
||||
- Baseline rows: `residual 3248 _action_charge_perform [size 3216!=3248, sha]`, `residual 944 _action_charge_setup [sha]`,
|
||||
20 EXACT. No parks for the unit.
|
||||
- Read in full: all nine action_charge ledgers (2026-08-21 two-leaf, the three 2026-08-26 math-helper ledgers,
|
||||
2026-08-28 public residuals, 2026-08-29 helper reintegration, 2026-09-06 authentic math header owners,
|
||||
2026-09-14 fresh-graphs, 2026-09-14 150K w2), `scratch/workers/action_charge.md`, the 100K handoff,
|
||||
`scratch/w2/laws_w2.md` and `scratch/w3/laws_w3.md` in full.
|
||||
- `git log --all --oneline -- source/ai/action_charge.c`: 16 refs. `branch_sweep`: 13 unique blobs, HEAD is the best
|
||||
(`exact 20 residual 2 unwritten 0 sizedelta 32`); nothing to reuse.
|
||||
- Scratch: `scratch/workers/w3c_action_charge/` — `base.c/.obj`, `p1.c/.obj`, `p2.c/.obj`, `setup_aln.txt`,
|
||||
`perform_aln.txt`, `perform_aln_full.txt`, `p1_aln.txt`. Worker notes: `scratch/workers/w3c_action_charge.md`.
|
||||
|
||||
## 2. `_action_charge_setup` — the shape space is closed
|
||||
|
||||
`alndiff` against the HEAD build (`setup_aln.txt`):
|
||||
|
||||
```
|
||||
target 291 instructions, ours 291 instructions
|
||||
--- delete target[67:68] ours[67:67] @T 0xe4 T e4 mov byte ptr [ebp - 1], 0
|
||||
--- insert target[88:88] ours[87:88] @O 0x138 O 138 mov byte ptr [ebp - 1], 0
|
||||
```
|
||||
|
||||
(the three other reported blocks are `__FILE__`/`.rdata` label artifacts of `--source`, not code differences).
|
||||
|
||||
January's `[ebp-1]` writes: `+0x45 = 1` (the sunk `boolean result = TRUE;` initializer — no entry store, so A42's
|
||||
"VC7 does not hoist a FALSE into the entry" detector says `+0xe4` is a *separate* source statement), `+0xbc = 0`
|
||||
(swarm arm), `+0xe4 = 0`, `+0xea = 0` (inhibited arm), `+0x107 = 0` (notarget arm), `+0x308 = 1` (melee success),
|
||||
`+0x383 = al` (vehicle arm), read once at `+0x39a`.
|
||||
|
||||
Context of the divergence:
|
||||
|
||||
```
|
||||
d9 mov cl, byte ptr [eax + 0xb6]
|
||||
df add esp, 8
|
||||
e2 test cl, cl
|
||||
e4 mov byte ptr [ebp - 1], 0 <-- between the compare and the jcc
|
||||
e8 jns 0xfc
|
||||
ea mov byte ptr [ebp - 1], 0
|
||||
ee mov word ptr [edi + 0x190], 3
|
||||
```
|
||||
|
||||
**A38** (initializer / zero-store placement) fires exactly: a store emitted between an `if`'s compare and its `jcc`
|
||||
belongs to the block *enclosing* that `if`, not to its body — i.e. the source statement sits before
|
||||
`if (TEST_FLAG(unit->object.damage_flags, _object_melee_attack_inhibited_bit))`.
|
||||
|
||||
**Closure proof (new).** Both bodies emit four zero stores to `result`. In any source where every path assigns
|
||||
`result` exactly once, the fourth store is the default for the deep melee-attempt path, and its only non-redundant
|
||||
position is inside that arm — which is the landed H1 shape and emits at `+0x138`. Conversely a store emitted at
|
||||
`+0xe4` necessarily precedes the inhibited test, where it dominates the inhibited and notarget arms; those arms'
|
||||
own stores cannot be dropped (w2 measured A1 "pre-store only" at 1024 and A6 "arm stores only" at 1056 — removing
|
||||
them re-creates nine tail-duplicated epilogues). Hence **strict EXACT requires a store that is redundant with
|
||||
respect to two arms**, and the eleven alternatives already measured in w2 (A1, A4, A6, R1, R1b, R2, R3, H1, H3,
|
||||
S2a, S5) are exhaustive of the non-redundant space. No shape was spent this wave; the proof replaces the probe.
|
||||
|
||||
The strict-EXACT body already exists: `scratch/workers/action_charge/w2/v3.c` (21/22 object) = the landed file with
|
||||
`result = FALSE;` moved one source line, from the top of the melee-attempt arm to immediately before the inhibited
|
||||
`if`. Class: laws_w3 C3 "Byte-proven redundant stores/branches (A42)", alongside `_encounter_test_rule` (tr8) and
|
||||
`_extract_sequence`.
|
||||
|
||||
**Owner ruling requested (re-stated, with the new closure proof): +944 padded strict-exact bytes for one moved
|
||||
source line, zero sibling and zero park risk.**
|
||||
|
||||
## 3. `_action_charge_perform` — the `[size]` gap attributed, and the linkage route improved
|
||||
|
||||
Production: 3216 / 84, **983 instructions vs January's 982**, relocation multiset identical.
|
||||
|
||||
### 3.1 The 32-byte gap is one cross-jump
|
||||
|
||||
January emits the `direction = prop->actor_to_prop;` struct copy twice:
|
||||
|
||||
```
|
||||
6c8 mov eax,[ebp-8] <- then-arm of `if (dot_product3d(&direction,&prop->actor_to_prop) < 0.f)`
|
||||
6cb fld dword ptr [__real@00000000] (distance = 0.f, interleaved)
|
||||
6d1 mov ecx,[eax+0xe0] / 6d7 mov edx,[eax+0xe4] / 6dd mov eax,[eax+0xe8]
|
||||
6e3 mov [ebp-0x2c],ecx / 6e6 mov [ebp-0x28],edx / 6e9 mov [ebp-0x24],eax
|
||||
...
|
||||
707 mov eax,[ebp-8] ... (second copy, different register schedule) <- inside `if (distance == 0.f)`
|
||||
```
|
||||
|
||||
Ours emits it once at `+0x6e7`: the inlined `dot_product3d(&direction, &prop->actor_to_prop)` strength-reduces the
|
||||
argument address to `add edx,0xe0` at `+0x6a1`; both copies then become the identical `mov ecx,[edx] …` sequence
|
||||
and VC7 cross-jumps them. The eight-instruction target block against our one-instruction stub *is* the
|
||||
`3216 != 3248` delta. The same biased pointer also reorders the inlined dot: January k,j,i (A35(2)
|
||||
youngest-term-first), ours j,k,i.
|
||||
|
||||
**Detector caveat for A35 (new):** a k,j,i vs j,k,i term order can be an addressing-mode artifact of a
|
||||
strength-reduced `&struct->field` pointer rather than a source expression-order or leaf-age fact. Look for an
|
||||
`add reg,imm` bias in the candidate before spending an A35 shape on term order.
|
||||
|
||||
### 3.2 The linkage lever, reproduced and improved
|
||||
|
||||
| Shape | Size / relocs | perform sha16 | Siblings | Owner census | Landed |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| HEAD (rename package + 11 local helper definitions) | 3216 / 84 | `2e9beea61ca0c704` | 20 EXACT | unchanged | (in tree) |
|
||||
| `p1.c` = HEAD + `__inline` on the 11 local definitions (w2 `v4_inline`) | 3264 / 84 | `798a99326c8aff1a` | 20 EXACT | unchanged | no |
|
||||
| `p2.c` = HEAD with the rename package **and** the 11 local definitions **deleted** (helpers come from `math/real_math.h`) | 3264 / 84 | `798a99326c8aff1a` | 20 EXACT | `+_magnitude_squared3d` (code) | no |
|
||||
|
||||
`p1` and `p2` produce **byte-identical** perform sections, so inline *linkage* is the only operative variable; the
|
||||
local `__inline` copies are not needed to obtain it. `p2` is the better-motivated form: January's map atlas marks
|
||||
`normalize2d`, `point_from_line3d`, `magnitude3d`, `normalize3d` and `collision_test_line` as inline (`i`) COMDAT
|
||||
copies, and `p2` removes an A30/R8-class per-TU `#define helper helper_inline` rename package plus 114 lines of
|
||||
duplicated real_math bodies from a consumer `.c`. Its only cost is one surplus candidate-only COMDAT
|
||||
`_magnitude_squared3d`, the same real_math.h select-any class as this object's already-disclosed
|
||||
`_vector_from_points3d`.
|
||||
|
||||
Neither reaches 3248, so under brief section 6 (already-written residual: land only if strict EXACT) neither is
|
||||
landable, and the fresh-graphs lane's decline of the `__inline` route stands. Recorded so a later wave does not
|
||||
re-litigate the linkage question.
|
||||
|
||||
### 3.3 Residual after the lever (59 real blocks, `p1_aln.txt`)
|
||||
|
||||
109 aligned blocks, 59 after removing relocation-annotation and branch-offset noise (HEAD base: 67). All are
|
||||
allocation:
|
||||
|
||||
- extra `mov ecx,[ebp-8]` prop reload at `+0x256` (+3 bytes; the only instruction-count difference);
|
||||
- melee-abort byte pair swapped — January `check_range` at `[ebp-2]`, `berserk_ranges` (and the later `melee`) at
|
||||
`[ebp-1]`; January also keeps `check_range` in BL across `game_time_get` where ours keeps `prop` in EBX and
|
||||
reloads the flag (`mov al,[ebp-1]; test al,al` at `+0x387`, +5 bytes);
|
||||
- `_charge_goal_melee` rematerialised as an immediate by January (`cmp word [edi+4],2`, `mov word [edi+4],2`) vs
|
||||
pinned in ECX by us (`mov ecx,2` … `cmp word [edi+4],cx`) — the constant-register pinning family, inverted;
|
||||
- `[ebp-0x14]` vs `[ebp-0x18]` for the tail `unreachable` byte;
|
||||
- two commutative `fadd` operand orders at `+0x944` / `+0x956` — R3 forbids swapping the source operands for these;
|
||||
- cdecl-pop (`add esp,N`) placement at `+0x6a2`, `+0x8e7`, `+0x919` (A31(a));
|
||||
- roughly 35 pure eax/ecx/edx register-name substitutions.
|
||||
|
||||
Net 3252 meaningful vs January's 3246.
|
||||
|
||||
## 4. Shapes spent and rejected
|
||||
|
||||
- setup: 0 this wave (closure proof; the 11 w2 alternatives are exhaustive of the non-redundant space).
|
||||
- perform: 2 of 5 (`p1`, `p2`), neither exact, neither landed.
|
||||
- Designed and rejected on paper: setup S1 (split the inhibited else-if into `if`/`else` with one default in the
|
||||
else) — yields three zero stores, not January's four, so it cannot be exact.
|
||||
- Not re-spent (prior do-not-repeat): declaration order / block scope / names / dead initialisers of `leap` and the
|
||||
tick outputs; early-return arms; `check_range` / `berserk_ranges` / `abort_range` / `time` / `target_range` /
|
||||
`unreachable` declaration order and scope; dot_product3d argument order; `danger + attack` order; moving perform
|
||||
before the helper package.
|
||||
|
||||
## 5. Checks
|
||||
|
||||
- Final real-file gate (no guard): `== exact 20 residual 2 unwritten 0`, listing identical to baseline row for row.
|
||||
- Guard gate: fails only on the pre-existing genuine `_point_from_line3d` owner (one definition, 48 bytes, EXACT).
|
||||
- Parks: `scratch/parkcheck.py` → "no parks for source/ai/action_charge".
|
||||
- Owner census vs `build/base`: HEAD `candidate-only vs base: []`; `p1` `[]`; `p2` `[('_magnitude_squared3d','code')]`.
|
||||
Pre-existing non-target owners (`_vector_from_points3d`, `__real@3f000000`, `__real@41f00000`, the two assert
|
||||
literals, the D3D tables) unchanged in all three.
|
||||
- `tools/fake_match_scan.py source/ai/action_charge.c`: 0 review leads.
|
||||
- `git diff --stat -- source/ai/action_charge.c`: empty.
|
||||
|
||||
## 6. Proposals
|
||||
|
||||
1. **Owner ruling (setup, A42/R12 class):** admit `scratch/workers/action_charge/w2/v3.c`. One moved source line
|
||||
(`result = FALSE;` before the inhibited `if`, arms unchanged) for +944 padded strict-exact bytes. This wave adds
|
||||
the proof that no non-redundant spelling can reach exact, so the ruling is the only remaining path for this row.
|
||||
2. **Census/policy note (perform):** if a later wave closes the allocator items, the linkage prerequisite should be
|
||||
taken via `p2.c` (delete the rename package and the local helper bodies) rather than the declined local
|
||||
`__inline` form; the orchestrator would then need to accept `_magnitude_squared3d` as a real_math.h surplus
|
||||
select-any disclosure, the same class as this object's existing `_vector_from_points3d`.
|
||||
|
||||
## 7. Reopen criteria
|
||||
|
||||
- **setup:** the owner ruling in section 6.1. Do not re-spend on store placement, declaration order, block scope or
|
||||
early-return shapes.
|
||||
- **perform:** a source-level cause, measured on the `p2` base, for (a) the `[ebp-1]`/`[ebp-2]` byte-pair rank in the
|
||||
melee-abort block that also puts `check_range` in BL, and (b) the `+0x256` prop reload. Do not re-spend on
|
||||
declaration order/scope of the abort-block locals, dot_product3d argument order, or commutative `fadd` swaps (R3).
|
||||
@@ -1,148 +0,0 @@
|
||||
# `action_charge.obj`: perform reconstruction and setup frame residual (Opus 5 fresh-graphs lane, 2026-09-14)
|
||||
|
||||
## Result
|
||||
|
||||
- `_action_charge_perform` (3,248 padded, previously UNWRITTEN) is now a complete typed-C body, landed as
|
||||
**fuzzy** (exact credit 0): 3,216 / 84 relocations vs 3,248 / 84, identical relocation destination multiset.
|
||||
- `_action_charge_setup` (944-byte residual) was reconstructed to **944 / 29 with identical instruction opcodes**;
|
||||
only frame-slot displacements differ. It is **not landed** (not strict exact).
|
||||
- All 20 baseline-exact functions stay strict exact with unchanged normalized hashes.
|
||||
- Object: `== exact 20 residual 2 unwritten 0 (of 22 listed)` (baseline `exact 20 residual 1 unwritten 1`).
|
||||
No newly exact function.
|
||||
|
||||
## 1. Scope and provenance
|
||||
|
||||
- Unit `source/ai/action_charge.c`, target `build/split/source/ai/action_charge.obj`, lane base `47d9dd0da`.
|
||||
- XDK 3911 `CL 13.00.9254` with `/O2 /Oy- /DDEBUG /Dxbox` (unchanged; `/O2` auto-inlines, see section 6).
|
||||
- Evidence used: January COFF disassembly (Capstone, relocation-annotated), Ghidra 12.1.2 decompilation
|
||||
`scratch/ghidra/out/action_charge.obj.decomp.c` (perform 383-832, setup 891-1039), January map atlas
|
||||
`scratch/atlas/action_charge.obj.txt`, HCEA `src/blam/ai/action_charge_perform.c` / `action_charge_setup.c`
|
||||
(later build, semantics only), `source/ai/ai_debug.c` charge-decision and melee-check renderers (field meanings),
|
||||
`source/ai/actor_firing_position.c` weapon minimum-range idiom, `source/ai/action_fight.c`
|
||||
`actor_perception_unreachable` prototype.
|
||||
- Prior work read in full: the seven existing action_charge ledgers and the archived frontier ledger
|
||||
`677defb9d:docs/object_matching_logs/action_charge_obj.md` (its perform/setup bodies were never committed;
|
||||
branch_sweep over 11 blobs found no body in any lane).
|
||||
|
||||
## 2. Validated baseline
|
||||
|
||||
| Function | Target padded | Relocs | Baseline | Now |
|
||||
| --- | ---: | ---: | --- | --- |
|
||||
| `_action_charge_perform` | 3,248 | 84 | UNWRITTEN | fuzzy 3,216 / 84, sha16 `2e9beea61ca0c704` (target `9ed9d44b1e9fd722`); first divergence +0x256 |
|
||||
| `_action_charge_setup` | 944 | 29 | 688 / 20 | unchanged in production; best candidate 944 / 29 sha16 `31040fe5ab789ce3` (target `34c0c115890ecab8`); first divergence +0x3 (`sub esp,0x24` vs `0x20`) |
|
||||
| 20 others | 1,984 | | EXACT | EXACT, hashes unchanged |
|
||||
|
||||
Data: production now also owns the target literals `__real@3f5db3d7`, `__real@3cbf258c`, `__real@3e99999a`,
|
||||
`__real@3d4ccccd`, `__real@3f4ccccd` (perform). `__real@41f00000` and the `!actor->meta.swarm` string are
|
||||
emitted for references January resolves as undefined externals. The setup-only
|
||||
`actor %s melee animation has no damage keyframe` string stays absent until setup lands.
|
||||
|
||||
## 3. Accepted controls (production)
|
||||
|
||||
`action_charge_perform`, placed between the helper package and the private destination helper:
|
||||
|
||||
- declarations in January call order: actor, actor definition (`actr`), variant definition (`actv`), firing variant,
|
||||
charge state, `prop = NULL`, `result = FALSE` (January keeps `[ebp-3]` and returns it on the default path);
|
||||
- prop-valid branch first with the "no target" arm last (`je` to +0x43c); a separate delayed-projectile arm
|
||||
(January lays `advancing = TRUE` right after that test and cross-jumps the vehicle-goal arm into it);
|
||||
- stalking exposure assigned to `state_data->stalking_currently_exposed` and re-read (January materialises it at
|
||||
32-bit width, which a boolean local does not reproduce);
|
||||
- close-range bounds with the `actor_firing_position.c` `MAX(minimum_range, weapon->weapon.ai_minimum_target_range)`
|
||||
idiom (weapon +0x40c);
|
||||
- melee abort: `MIN(abort_range, maximum_abort_range)` with a named `maximum_abort_range = MAX(0.f, melee_attack_range) + 0.8f`
|
||||
(January stores it to a slot and compares with `fcom`), asserts at lines 288 and 487;
|
||||
- melee check debug telemetry into `actor_debug_array` (`last_melee_time`, `field_108/114/120/12C/138/139/13C/148/14C`)
|
||||
exactly as `ai_debug.c` renders it;
|
||||
- `dot < 0` if/else distance form (two separate `direction = prop->actor_to_prop` copies in January),
|
||||
leap arm `distance < lower && unreachable_ticks == 0 && !flying` aborts, ballistic leap with January's argument
|
||||
mapping (13th = vertical, 14th = horizontal);
|
||||
- communication immediates as enums: `_ai_communication_melee` (43), `_comm_hostility_enemy` (3);
|
||||
- tail: `target_prop` re-fetch with `out_of_range = FALSE; if (...) out_of_range = TRUE;` (January `xor cl,cl` form),
|
||||
single `return result;`.
|
||||
|
||||
Supporting source-local additions: includes `ai.h`, `ai_communication.h`, `items/projectiles.h`,
|
||||
`items/weapon_definitions.h`, `ai_debug.h`; enum constants `_action_charge_prop_facing_central = 2`,
|
||||
`_action_charge_prop_closing_speed_slow = 1`; TU-local `actor_perception_unreachable` prototype (same as action_fight.c).
|
||||
The `(real_vector2d *)` casts on 3D vectors follow `actors.c` and January's call operands (the 3D aim vector's address
|
||||
is passed to `normalize2d`).
|
||||
|
||||
## 4. Experiment matrix
|
||||
|
||||
Scores are differing instructions after alignment (`scratch/workers/action_charge/score.py`, relocation offsets normalised).
|
||||
|
||||
### perform
|
||||
|
||||
| Shape | Size / relocs | Diff insns | Kept |
|
||||
| --- | --- | ---: | --- |
|
||||
| first complete body | 3280 / 87 | - | no |
|
||||
| prop-valid first, delayed arm split, exposure via state | 3248 / 87 | - | yes |
|
||||
| named maximum_abort_range | 3216 / 84 | 144 | yes |
|
||||
| dot<0 if/else, leap-abort polarity, order fixes (package helpers) | 3216 / 84 | 202 | yes (authentic form; package merges copies) |
|
||||
| same, helpers marked `__inline` locally (not landed) | 3264 / 84 | 142 | lever only |
|
||||
| check_range/berserk declaration orders (3 variants) | = | 140-141 | inert |
|
||||
| target_range/time scopes (3 variants), unreachable scope | = | 140-141 | inert |
|
||||
| `field_114` component copy | = | 135 but loses January's pointer copy | no |
|
||||
| `target_prop` + if-form out_of_range, declaration order | = | 127 (`__inline` mode) / 182 (production) | yes |
|
||||
| abort ternary as if/else, compare operand swap | = | 127 | inert |
|
||||
| dot_product3d argument swaps, danger/attack sum order | = | 142 | inert (VC7 canonicalises) |
|
||||
|
||||
### setup (best candidate `scratch/workers/action_charge/setup_v12.txt`, not landed)
|
||||
|
||||
| Shape | Size / relocs | Notes |
|
||||
| --- | --- | --- |
|
||||
| single exit + debug decisions + assert + csmemset + keyframe error | 1040 / 29 | 9 tail-duplicated epilogues |
|
||||
| + `result = FALSE` in inhibited/notarget arms (January stores at +0xbc/+0xe4/+0xea/+0x107) | 1040 / 29 | removing them later re-creates the duplication |
|
||||
| + `move_range = MAX(minimum_move_range, target_range)` | 928 / 29 | duplication gone |
|
||||
| + `state_data->leap_possible_if_at_range = real_random() < chance; leap = ...` | **944 / 29** | 32-bit compare width as January; only frame displacements differ |
|
||||
| frame diagnostics: 16 declaration-order / scope / name / init / `valid` / variant-local variants, `/Fa` listings | 944 / 29 | `leap` and `end_tick` never share January's 4-byte cell |
|
||||
|
||||
## 5. Do-not-repeat
|
||||
|
||||
- perform: declaration order and block scope of `check_range`, `berserk_ranges`, `abort_range`, `time`,
|
||||
`target_range`, `unreachable`; dot_product3d argument order; `danger + attack` operand order; moving perform before
|
||||
the helper definitions (VC7 compiles bottom-up; identical output).
|
||||
- setup: declaration order, block scope, names, dead initialisers of `leap` / tick outputs; removing `valid`; variant
|
||||
pointer vs name local; `leap = cmp ? TRUE : FALSE` / `(long)` casts (keep 8-bit width).
|
||||
- Pure header helpers (removing the rename package) emit candidate-only `_magnitude_squared3d` (LNK2005 history in
|
||||
`action_charge_obj_jonas_math_helper_recovery_rejection_20260826.md`); do not land that.
|
||||
|
||||
## 6. Residual classification
|
||||
|
||||
- perform (measured): relocation multiset identical; remaining differences are register choices (melee-abort block
|
||||
`check_range` in BL vs `prop` in EBX; `field_114` and `field_12C` copy registers; argument registers of
|
||||
`unit_melee_attack_begin` / `ai_communication_event`), byte-cell packing of `berserk_ranges` / `check_range`, and
|
||||
x87 operand order of three inlined dot products. **Inference, with a measured lever:** the inherited
|
||||
NODUPLICATES helper package lets VC7 use normalize3d/normalize2d clobber sets (EDX kept live across the call);
|
||||
January's helpers were SELECT_ANY inline COMDATs (atlas `i` records), so its caller could not. Marking the local
|
||||
helper definitions `__inline` keeps all 11 helpers strict exact with no new owner and cuts perform's residual from
|
||||
182 to 127 instructions. Not landed because it changes exact siblings' linkage.
|
||||
- setup (measured): instruction stream identical; residual is frame layout only (January frame 0x20 with `leap` at
|
||||
-8 and `end_tick` at -6 in one cell; candidate 0x24). No source lever found.
|
||||
|
||||
## 7. Reopen criteria
|
||||
|
||||
- Orchestrator decision on helper linkage (local `__inline` package, or header-owned helpers with January's
|
||||
`magnitude3d` body that does not reference `magnitude_squared3d`), then continue perform from
|
||||
`scratch/workers/action_charge/pbase3.txt` on that base.
|
||||
- For setup: evidence of the original tick-output locals/types that makes `leap` and `end_tick` non-interfering for
|
||||
VC7's frame packer; land `setup_v12.txt` together with the destination-helper signature
|
||||
`(long actor_index, short goal, real_point3d const *melee_target_point)` only when strict exact.
|
||||
|
||||
## 8. Disposition
|
||||
|
||||
Object remains NonMatching: 20 strict exact, `_action_charge_perform` fuzzy (credit 0), `_action_charge_setup`
|
||||
residual. No config, header, park, flag or comparator change.
|
||||
|
||||
## Lead admission notes (2026-09-14)
|
||||
|
||||
- The worker's TU-local `actor_perception_unreachable` prototype was replaced
|
||||
by the owning declaration added to `source/ai/actor_perception.h` in the
|
||||
separate prerequisite commit `a694cf1b2` (which also removed action_fight.c's
|
||||
consumer-local copy). `action_charge.c` now includes that header.
|
||||
- The leap stores were reordered to the natural `leap_pending = TRUE` first,
|
||||
as measured by the adversarial reviewer; the emitted body is byte-identical
|
||||
(3216/84, sha16 `2e9beea61ca0c704`).
|
||||
- The proposal to mark the 11 local math helpers `__inline` was NOT adopted:
|
||||
it changes COMDAT selection of 11 already-exact sections without an exact
|
||||
gain and needs its own whole-board review. `_action_charge_perform` remains a
|
||||
zero-credit fuzzy body; `_action_charge_setup` stays at its baseline residual.
|
||||
-129
@@ -1,129 +0,0 @@
|
||||
# `action_converse.obj`: ordinary-C restoration and fuzzy park
|
||||
|
||||
## Outcome
|
||||
|
||||
`source/ai/action_converse.c` now contains a credible ordinary-C
|
||||
reconstruction of `action_converse_perform`. The former implementation used
|
||||
three inline-assembly regions to transcribe January's shared-`TRUE` register
|
||||
choice. That was an exact machine-code reproduction, not credible original
|
||||
gameplay source, and is not allowed by the rule limiting sparse inline
|
||||
assembly to helper and math functions.
|
||||
|
||||
The ordinary-C function is intentionally retained at the measured compiler
|
||||
boundary:
|
||||
|
||||
- object-local strict result: `8 / 9` functions, `640 / 896` padded bytes;
|
||||
- target packet: `256` padded bytes, `8` relocations,
|
||||
normalized SHA-256
|
||||
`7a3fad8fb69307c132558b906832d4d31f0334734fc76d18fe773189b5a38d5d`;
|
||||
- base packet: `256` padded bytes, `8` relocations,
|
||||
normalized SHA-256
|
||||
`288862a662942eb5b03ee84809dbd6b6aea1c023d52915f2bc373192e7c212cb`;
|
||||
- objdiff fuzzy score: `93.14815%`;
|
||||
- park class: `register-allocation`.
|
||||
|
||||
No exact-match credit is claimed for this function.
|
||||
|
||||
## Source credibility and semantics
|
||||
|
||||
The retained topology is the clean donor preserved at
|
||||
`C:\halo-worktrees\opus-dual-scheduler-research\dispo-wt`, commit
|
||||
`5ac58ab8731e9227de6fd87afdf0542ce318aa59`. The same body originated in
|
||||
commit `b4651a63db29932d5a6640d0c7b5af59a13c8463`.
|
||||
|
||||
The function performs a coherent sequence:
|
||||
|
||||
1. Resolve the conversation's unit to a prop when no prop is cached.
|
||||
2. Mark the actor in range when the prop is fully perceived and inside the
|
||||
requested distance, or is closer than `0.7` world units.
|
||||
3. Halt movement once in range.
|
||||
4. Otherwise request movement toward the prop and record failure when that
|
||||
request fails.
|
||||
5. Record failure when no prop can be resolved.
|
||||
|
||||
This is not an accidental or nonsensical byte match. The state transitions,
|
||||
callee contracts, field offsets, and relocation identities agree with the
|
||||
January function. HCEA interface evidence at commit
|
||||
`570c83fd9c365dad6f2a3e7041705d5b84c7847c` supports the action-table return
|
||||
contract and the reconstructed behavior. The open Marathon source was
|
||||
checked as a naming/style reference, but it supplies no stronger homolog for
|
||||
this Halo-specific conversation action.
|
||||
|
||||
The numeric visibility threshold was replaced with the authentic enum
|
||||
constant `_actor_perception_full`. January accesses `prop->visibility`; an
|
||||
HCEA reconstruction using `team_index` at that point is inconsistent with the
|
||||
January offset and was not copied.
|
||||
|
||||
The local `true_value` declaration and assignment remain separate even though
|
||||
the general style preference is to combine them. This is the strongest
|
||||
measured natural-C packet, and moving its initialization is one of the already
|
||||
exhausted lifetime shapes.
|
||||
|
||||
## Residual compiler boundary
|
||||
|
||||
The target and base have the same eight relocation identities in the same
|
||||
order:
|
||||
|
||||
| Relocation | Target | Base |
|
||||
| --- | ---: | ---: |
|
||||
| `_actor_data` | `+4` | `+4` |
|
||||
| `_datum_get` | `+17` | `+16` |
|
||||
| `_prop_get_base_by_unit_index` | `+67` | `+63` |
|
||||
| `_prop_data` | `+107` | `+103` |
|
||||
| `_datum_get` | `+114` | `+110` |
|
||||
| `__real@3f333333` (`0.7f`) | `+157` | `+153` |
|
||||
| `_actor_move_halt` | `+186` | `+183` |
|
||||
| `_actor_move_to_prop` | `+220` | `+216` |
|
||||
|
||||
January retains `TRUE` in `EBX` and uses `BL` for the two byte stores. The
|
||||
lawful VC7 C output folds those values into immediate operands. Five grounded
|
||||
source shapes were exhausted without finding a credible C lever. The former
|
||||
asm forced the target register allocation directly and was therefore removed
|
||||
rather than treated as a reconstruction.
|
||||
|
||||
## Prototype ownership cleanup
|
||||
|
||||
The same wave removes use-site declarations and places the contracts with the
|
||||
closest associated headers:
|
||||
|
||||
- `prop_get_base_by_unit_index` is declared under `prototypes/PROPS.C` in
|
||||
`source/ai/props.h`;
|
||||
- `actor_move_to_prop` and `actor_move_halt` are declared under
|
||||
`prototypes/ACTOR_MOVING.C` in `source/ai/actors.h`, because
|
||||
`actor_moving.c` has no dedicated header;
|
||||
- `actor_move_halt` uses its authentic `boolean` return contract rather than
|
||||
the inaccurate local `void` declarations. Existing callers ignore the
|
||||
value, so their call behavior is unchanged;
|
||||
- duplicate declarations were removed from `actions.c`, `action_charge.c`,
|
||||
`action_converse.c`, `action_fight.c`, `action_guard.c`, `action_search.c`,
|
||||
`action_wait.c`, and `ai_communication.c`.
|
||||
|
||||
All project real-valued parameters use `real` from `cseries.h`; no raw
|
||||
`float` interface was introduced.
|
||||
|
||||
## Verification
|
||||
|
||||
- Focused VC7 compile of `build/base/source/ai/action_converse.obj`: pass.
|
||||
- Full configured build, semantic report, admission audit, and progress gate:
|
||||
pass with `0` unit errors.
|
||||
- `tools.coff_compare` confirms the packet sizes, hashes, and relocation
|
||||
identities above.
|
||||
- The pre-change regression manifest reports exactly one intentional change:
|
||||
the formerly accepted asm transcription is now nonexact. All eight
|
||||
inherited strict-exact Action Converse functions remain exact.
|
||||
- Park validation: `13` active, `0` stale, `0` invalid.
|
||||
- Strict campaign board after the cleanup: `278 / 619` fully exact objects,
|
||||
`4,857 / 8,246` strict-exact functions, and
|
||||
`674,823 / 1,922,669` padded bytes. The perform function is counted as
|
||||
parked, not exact.
|
||||
- Test suite: `212 passed`.
|
||||
- `git diff --check`: pass.
|
||||
- The rebuilt object has no `point_from_line3d` symbol or COMDAT; geometry and
|
||||
the January inline schedule are untouched.
|
||||
|
||||
Raw object hashes for the frozen verification build:
|
||||
|
||||
- target `action_converse.obj`:
|
||||
`9a69bb69f5590a576fd82f635f47fdcb037b6ce5410d5ce2e5b4d3bd92510a35`;
|
||||
- base `action_converse.obj`:
|
||||
`e12f04462cff30aa8d59e15ff5d64a786ebc5d19506ed5147103a34848dc731b`.
|
||||
@@ -1,126 +0,0 @@
|
||||
# `action_flee.obj` Jonas two-leaf wave
|
||||
|
||||
## Result
|
||||
|
||||
This bounded source-only wave starts from authoritative integration commit
|
||||
`a03585774f859697a788a73e4c3fa6bde7c6e3ea`. Six HCEA-backed action-flee
|
||||
bodies were emitted together in one natural candidate compile. Two were
|
||||
independently strict and are retained. The four nonexact bodies and their
|
||||
support-only declaration were removed immediately, without a spelling,
|
||||
declaration, control-flow, or compiler-control retry. `action_flee.obj`
|
||||
advances from 0/13 to 2/13 exact functions and remains `NonMatching`.
|
||||
|
||||
| Retained function | Meaningful | Padded | Relocations | Normalized SHA-256 |
|
||||
| --- | ---: | ---: | ---: | --- |
|
||||
| `_action_flee_end` | 41 | 48 | 3 | `649eb65fd4e8e516d5c8675b4dbf5e08dab7b6d07888e25af8327f32b5c6be98` |
|
||||
| `_action_flee_blind_panic` | 30 | 32 | 0 | `7bcf33bcce1177b460ded4cc5dee5518afa9db14695e8fdd49652483675b6297` |
|
||||
| **Wave gain** | **71** | **80** | **3** | |
|
||||
|
||||
The hardened COFF comparator proves identical padded bytes and exact
|
||||
relocation addresses, types, destinations, and addends for both retained
|
||||
functions. The object now reports 71/3,312 meaningful code bytes and two
|
||||
exact functions. The target's remaining eleven functions and all 312
|
||||
non-code bytes stay outside this wave's credit.
|
||||
|
||||
## Provenance and signatures
|
||||
|
||||
- Baseline `source/ai/action_flee.c` blob:
|
||||
`73990e6dee5af609201a2b17af56424f3276161a`.
|
||||
- Retained source blob/SHA-256:
|
||||
`65b90ce0ba18f6e01c13ef33c8b6bd539db16079` /
|
||||
`67e862acfb2a040c4a652ecbe85c842d1a9869a3159eefc9bc3059bb351874b7`.
|
||||
- January executable SHA-256:
|
||||
`4cc87b45f721270392a96f1674ed2b5cd4a7bb4355faeab4531d1cf1884d9520`.
|
||||
- January split-object SHA-256:
|
||||
`5d6e667103c4b42824a5e1c69fb047860a60d901eda36153162cf19672eff59e`.
|
||||
- Clean HCEA semantic donor commit:
|
||||
`c168af2e747d3095d9a29418ae401f3a39544863`. Its exact-name
|
||||
`action_flee_end.c`, `action_flee_flush_position_indices.c`,
|
||||
`action_flee_modify_color.c`, `action_flee_replace_prop.c`,
|
||||
`action_flee_blind_panic.c`, and `action_flee_begin.c` files supply the
|
||||
six natural typed behaviors.
|
||||
- January PC disassembly independently fixes 32-bit actor datum handles,
|
||||
the `actor_get`/`datum_get` path, the named flee-state offsets, the signed
|
||||
panic interval `[9, 12]`, and both unit blind-running calls. January COFF
|
||||
remains authoritative for symbol identity, bytes, padding, and relocation
|
||||
ownership.
|
||||
- Compiler: Microsoft 32-bit C/C++ Optimizing Compiler `13.00.9254.1` for
|
||||
80x86, with the repository's unchanged XDK 3911 command and flags.
|
||||
|
||||
The retained signatures are:
|
||||
|
||||
```c
|
||||
void action_flee_end(
|
||||
long actor_index);
|
||||
boolean action_flee_blind_panic(
|
||||
short panic_type);
|
||||
```
|
||||
|
||||
The existing `actors.h` owns the typed actor/action layout and `actor_get`
|
||||
contract. The existing `units.h` declaration owns the stop-running call.
|
||||
No shared-header repair is needed.
|
||||
|
||||
## Authenticated behavior and one-shot rejection record
|
||||
|
||||
`action_flee_end` resolves the complete 32-bit actor handle through
|
||||
`actor_get`; when the actor owns a valid unit datum, it calls the typed
|
||||
`unit_stop_running_blindly` API. `action_flee_blind_panic` returns true only
|
||||
for the inclusive signed-short interval from grenade attachment through
|
||||
burning to death, represented by the source-local enum values 9 and 12.
|
||||
Both bodies have explicit terminal returns.
|
||||
|
||||
All six candidates were compiled together once. The following four misses
|
||||
were removed without retry:
|
||||
|
||||
| Rejected function | Target meaningful / padded / relocs | Target hash | First natural candidate |
|
||||
| --- | ---: | --- | --- |
|
||||
| `_action_flee_flush_position_indices` | `39 / 48 / 2` | `8dad23011290d89f5753258c4f1a2c41b21837956d5556a5de2c9a344de11329` | `48 / 2`, SHA `8da380385d9a8cfbb0f1465c1bef5c314add784ef72b616032e8646cded81413`; same relocation identities, different normalized instruction schedule. |
|
||||
| `_action_flee_modify_color` | `99 / 112 / 4` | `9eef0cd0460952e50234aa38cad6a232cef2ed909f574428956b38026790dfb2` | `80 / 4`, SHA `61e086d8f401f02517b7ad56f1938c82a0121a05b697fba3cc11b86747d8685d`; the optimizer joined the color-copy tails instead of January's duplicated branches. |
|
||||
| `_action_flee_replace_prop` | `48 / 48 / 2` | `10b5ae0e39ea2d834df55c0984c57bad0465ad8ee69612fc6cc02a1f7762cbf0` | `48 / 2`, SHA `48b2a3f2fe62a1474a20508f3c90d3866f70e390310adee035f55fd0db12bbf4`; same relocation identities, different normalized instruction schedule. |
|
||||
| `_action_flee_begin` | `92 / 96 / 3` | `009e97240ce60b10098e18f6f625c4b678cd424dd832d92d69e7a3eb485ea9a0` | `96 / 3`, SHA `1aa8574ec4ab3fee338e6ea51c0ad4be4b1e0a7b2098b18442f21131151c2fab`; the unit-start call relocation lands at `+79` instead of January's `+83`. |
|
||||
|
||||
All four rejected COMDATs and the begin-only unit-start declaration are
|
||||
absent from the final object. Reopen them only with independently preserved
|
||||
January source or a newly authenticated ordinary-C contract; do not tune
|
||||
their spelling or scheduling from this rejected object.
|
||||
|
||||
## Policy, scope, and validation
|
||||
|
||||
Only `source/ai/action_flee.c` and this new Jonas-owned ledger are changed.
|
||||
No shared header, storage definition, data section, configuration, frozen-five
|
||||
source, semantic exception, parked record, pre-existing Markdown, or
|
||||
Claude-owned file is edited.
|
||||
|
||||
The retained source is readable typed C. It contains no assembly, raw-address
|
||||
or byte-offset dereference, pointer/integer reconstruction, pointer or union
|
||||
pun, inactive-union access, undefined overflow, volatile scheduling device,
|
||||
force-inline annotation, optimizer pragma/barrier, synthetic anchor, or
|
||||
object-byte forcing. The final COFF defines only two code COMDATs plus debug
|
||||
metadata; it defines no `.rdata`, `.data`, `.bss`, COMMON symbol, or global
|
||||
storage.
|
||||
|
||||
- Complete `halobetacache_build` and `libcmt_build`: pass.
|
||||
- Direct hardened comparison: both retained functions pass; all four
|
||||
rejected symbols are absent from the final COFF symbol table.
|
||||
- Semantic audit: 470 units, 4,052 functions evaluated, 3,912 semantic
|
||||
exact, 101 hidden exact / 61,876 hidden code bytes, 3,973 accepted exact,
|
||||
and zero unit errors.
|
||||
- Campaign progress: 375/833 complete objects, 3,960/11,060 exact functions,
|
||||
475,638/2,198,102 meaningful code bytes, and
|
||||
1,835,088/4,176,062 matched data bytes. This wave adds two functions and
|
||||
71 meaningful bytes with no data increase.
|
||||
- Admission audit: zero candidates and zero revocations; only the inherited
|
||||
`source/shell/shell_xbox` completion-label contradiction remains.
|
||||
- Parked validation: three active, zero stale, and zero invalid entries.
|
||||
- Complete tooling suite: 179/179 tests pass; `git diff --check` is clean.
|
||||
|
||||
The fail-closed pre-wave check identifies exactly the two retained functions
|
||||
as `NEWLY_EXACT` and reports `changed_nonexact: []`. Adding the first two
|
||||
COMDATs necessarily changes the translation unit's debug section and symbol
|
||||
set, which the generic structural check surfaces for review; direct hardened
|
||||
comparison independently proves both accepted functions. No adjudication or
|
||||
configuration exception is added.
|
||||
|
||||
A clean committed-state snapshot/check followed by deletion and forced
|
||||
rebuilding of `action_flee.obj` is the final same-path reproducibility proof.
|
||||
No push is performed.
|
||||
@@ -1,133 +0,0 @@
|
||||
# `action_flee.obj` opus5 150K wave 2: park re-investigation (2026-09-14)
|
||||
|
||||
## Scope and provenance
|
||||
|
||||
- Translation unit `source/ai/action_flee.c`; target `build/split/source/ai/action_flee.obj`
|
||||
(January 2002 Xbox debug build, XDK 3911 / VC7 13.00.9254, repository flags unchanged).
|
||||
- Lane worktree `C:\halo-worktrees\opus5-150k-house-clean-20260914`, wave w2. Worker notes:
|
||||
`scratch/workers/actions_action_flee_etc.md`; scratch candidates in `scratch/workers/actions_action_flee_etc/`.
|
||||
- Ledgers read first: `action_flee_obj_jonas_two_leaf_20260821.md`,
|
||||
`action_flee_obj_update_semantic_owner_boundary_20260905.md`,
|
||||
`action_flee_obj_threshold_leaf_reconciliation_20260908.md`,
|
||||
`action_flee_obj_position_helpers_exact_20260909.md`, the three `config/parked.json` entries.
|
||||
- `branch_sweep.py source/ai/action_flee`: 10 blobs, none better than the current file.
|
||||
|
||||
## Baseline (real file, unchanged by this wave)
|
||||
|
||||
`== exact 10 residual 3 unwritten 0`, `_point_from_line3d` guard passes. All three residuals are parked:
|
||||
|
||||
| Function | Target | Base | Relocs | Gate tag |
|
||||
| --- | ---: | ---: | ---: | --- |
|
||||
| `_action_flee_setup` | 272 | 256 | 12 | size, sha |
|
||||
| `_action_flee_current_position_exposed` | 352 | 352 | 13 | sha |
|
||||
| `_action_flee_perform` | 864 | 848 | 30 | size, sha |
|
||||
|
||||
## Result
|
||||
|
||||
Production file **unchanged** (every target is parked). A scratch candidate reopens all three parks:
|
||||
|
||||
| Candidate | Gate | Notes |
|
||||
| --- | --- | --- |
|
||||
| `scratch/workers/actions_action_flee_etc/flee_c1.c` | 12 exact / 1 residual / 0 unwritten | setup and exposed strict EXACT; perform 864/30 sha-only |
|
||||
| `scratch/workers/actions_action_flee_etc/flee_c1diag.c` | **13 / 0 / 0** | c1 plus a diagnostic local `unit_is_speaking` prototype (NOT landable; proves the header proposal) |
|
||||
|
||||
Diff: `scratch/workers/actions_action_flee_etc/flee_park_reopen_c1.diff`. Every baseline EXACT row stays EXACT,
|
||||
the guard passes, the owner census against `build/base` shows no new or dropped owners (the three `real_math`
|
||||
select-any fallbacks are pre-existing), and `tools/fake_match_scan.py` reports 0 leads (HEAD also 0).
|
||||
|
||||
## Evidence per function
|
||||
|
||||
### Shared: `action_flee_find_flee_position` has a third parameter
|
||||
|
||||
HCEX.pdb (SHIP), `DIA2Dump -sym`, gives
|
||||
`static void action_flee_find_flee_position(long actor_index, unsigned char respect_direction, struct flee_state_data *flee_state_data)`.
|
||||
January's call sites prove the stack argument:
|
||||
|
||||
- setup +0xe1: `push 0; call; add esp,4`;
|
||||
- perform +0x1a6: `mov ebx,[ebp+8]; push 1; call; add esp,4`.
|
||||
|
||||
The callee never reads it, so its body stays EXACT (640/23) with the unused parameter. The candidate declares
|
||||
`boolean respect_direction` with a one-line disclosure comment. Setup passes `FALSE` and perform passes `TRUE`.
|
||||
The old two-parameter prototype was an ABI error, not a tie. It cost setup its frame spill: EBX has to carry
|
||||
`actor_index` into the call, so January spills the actor pointer to `[ebp-8]`.
|
||||
|
||||
### `_action_flee_setup`: strict EXACT (272/12, sha 1a415a0adece0dd5)
|
||||
|
||||
- The 3-parameter call fixes the size and the frame.
|
||||
- January loads `force_state_entry` first and emits the stores after `csmemset` as +5, +8, +0xc, +4, +0x1c, +0.
|
||||
The source order that reproduces this is: forced_flee_ticks, flee_firing_position_index = NONE, panic_type,
|
||||
flee_from_last_visible_location, allow_occluded_points, flee_prop_index.
|
||||
- This is store-order recovery for independent field initialisation, per the methodology case `lra_new`.
|
||||
- Shapes: v1 (prototype only), v2/v3/v4/v5b/c/e (other orders) were sha-only; v5d was EXACT.
|
||||
|
||||
### `_action_flee_current_position_exposed`: strict EXACT (352/13, sha 498dc2c046073108)
|
||||
|
||||
- **Wrong field in base.** At +0x130, January copies prop_datum +0xbc into `approach_point`. In our `props.h`
|
||||
layout, +0xbc is `body_position`: `definitely_located` is 0xb8, `abandoned_search` 0xbb, and `head_position` is
|
||||
+0x104, which is the pointer January passes to `ai_test_line_of_sight`.
|
||||
- Base copied `head_position`, the same error as the HCEA lift. The second use of `&prop->head_position` created
|
||||
the extra `[ebp-8]` pointer home, the 0x14 frame (January: 0x10) and the EBX/EDI swap.
|
||||
- The park's premise, "coherent EDI/EBX allocation, not missing behaviour", is refuted.
|
||||
- +0x16..+0x22: `exposed = FALSE` is stored after `datum_get`. By the store/call-order law, `actor` is declared
|
||||
before `exposed`.
|
||||
|
||||
### `_action_flee_perform`: strict EXACT only with the proposed prototype (864/30, sha d62f05304574f88e)
|
||||
|
||||
January facts that each correct the base:
|
||||
|
||||
| January bytes | Source fact |
|
||||
| --- | --- |
|
||||
| +0x40 `cmp [esi+2],0; jle; mov [esi+8],-1` | `if (flee_stationary_ticks > 0) { index = NONE; } else { ... }` (base had the inverted polarity) |
|
||||
| +0x109 `mov byte ptr [eax+0x74], bl` | prop +0x74 is `currently_damaging_me`; base wrote `unopposable_enemy` (+0xa4, HCEA's misnamed lift) |
|
||||
| +0x101/+0x106 `movsx ecx,cx` / `movsx ecx,dx` | `prop->perception = MAX(prop->audibility, prop->ineffability);` direct, int-promoted |
|
||||
| visibility, perception, damaging, LOS stores | statement order visibility, perception, currently_damaging_me, line_of_sight |
|
||||
| +0x255 `or eax,-1; cmp ecx,-1; je` | `cause_unit_index = NONE; if (flee_prop_index != NONE) cause_unit_index = prop_get(...)->unit_index;` |
|
||||
| +0x27a fall-through | the not-yet-communicated flee event is the then-arm; the idle event is the else-arm |
|
||||
| +0x2d3 `mov al,[edi+6]; test; jne 0x324` | the line-302 assertion is guarded by `if (!actor->meta.swarm)` |
|
||||
| +0x1a9 `push 1` | `respect_direction = TRUE` |
|
||||
| +0x1ea `test al,al; jne; mov [esi+0x10],al` | `unit_is_speaking` returns `boolean` |
|
||||
|
||||
The last row is an owner gap. No header declares `unit_is_speaking` (definition: `unit_dialogue.c:389`,
|
||||
`boolean unit_is_speaking(`), so `action_flee.c` compiles it as a C4013 implicit `int` and emits `test eax,eax`.
|
||||
With every other fix, the flee_c1 perform differs from January by that single instruction. The diagnostic
|
||||
candidate, which adds a local prototype, is strict EXACT.
|
||||
|
||||
Shapes: v6 (polarity, field, cause, arm order, swarm guard) gave 848. v6p (+ diagnostic prototype) gave 848. v7
|
||||
(perception after damaging) gave 848. v7b gave EXACT. v7n (v7b without the prototype) gave 864, sha-only.
|
||||
|
||||
## Proposals
|
||||
|
||||
1. **ORCHESTRATOR-PROPOSAL (header), `source/units/units.h`**. Insert after the `unit_notify_impulse_sound`
|
||||
prototype, before `unit_make_damage_sound`:
|
||||
|
||||
```c
|
||||
boolean unit_is_speaking(
|
||||
long unit_index);
|
||||
```
|
||||
|
||||
Evidence:
|
||||
- January +0x1ea `test al,al`;
|
||||
- the definition's return type;
|
||||
- punpckhdq `units.h:557` declares the same prototype at the same neighbourhood.
|
||||
|
||||
Consumers: 66 direct includers (`scratch/workers/actions_action_flee_etc/units_h_consumers.txt`). The
|
||||
declaration-count law applies, so a full build is required.
|
||||
|
||||
2. **park-reopen `_action_flee_setup` and `_action_flee_current_position_exposed`** from `flee_c1.c`. Both are strict
|
||||
EXACT without any header change.
|
||||
3. **park-reopen `_action_flee_perform`** from `flee_c1.c` once proposal 1 lands. If proposal 1 does not land, the
|
||||
reopen of (2) still changes perform's call site (`push 1`), so perform's park must be re-baselined to
|
||||
864/30 sha cefb8e42bcdf2d49.
|
||||
|
||||
## Do-not-repeat
|
||||
|
||||
- The two-parameter `find_flee_position` prototype.
|
||||
- `head_position` as the exposure approach point.
|
||||
- `unopposable_enemy` in perform's arrival block.
|
||||
- The `<= 0` stationary polarity.
|
||||
- A short perception local.
|
||||
|
||||
## Reopen criteria
|
||||
|
||||
- setup and exposed: met (January-proven ABI and field facts).
|
||||
- perform: land the `unit_is_speaking` prototype in its owner header.
|
||||
@@ -1,57 +0,0 @@
|
||||
# `action_flee.obj` - opus5 150K house-clean lane, wave w3 (2026-09-14)
|
||||
|
||||
## Scope and baseline
|
||||
|
||||
- Translation unit `source/ai/action_flee.c`; target `build/split/source/ai/action_flee.obj` (January 2002 Xbox debug, VC7 13.00.9254).
|
||||
- Worker notes: `scratch/workers/w3_path_smoothing_actor_firing_position_etc.md`; scratch dir `scratch/workers/w3_path_smoothing_actor_firing_position_etc/`.
|
||||
- Baseline real-file gate (guard passes): `== exact 12 residual 1 unwritten 0`. The only residual, `_action_flee_perform` (864/30), is parked
|
||||
(park base 864/30 `cefb8e42bcdf2d49`, target `d62f05304574f88e`).
|
||||
- Ledgers read: `action_flee_obj_jonas_two_leaf_20260821.md`, `action_flee_obj_update_semantic_owner_boundary_20260905.md`,
|
||||
`action_flee_obj_threshold_leaf_reconciliation_20260908.md`, `action_flee_obj_position_helpers_exact_20260909.md`,
|
||||
`action_flee_obj_opus5_150k_w2_20260914.md`; laws `scratch/w2/laws_w2.md` (C2, A7, R8, R9).
|
||||
- `branch_sweep.py`: best historical blob 10/3/0 (below the current file).
|
||||
|
||||
## Result
|
||||
|
||||
**The real file is unchanged** (final gate 12/1/0, guard passes, park drift 0/1, fake scan 0 leads). One header packet is proposed,
|
||||
measured with a shadow-header consumer census.
|
||||
|
||||
## `_action_flee_perform` - park reopen via a genuine units.h packet (no body change)
|
||||
|
||||
Law A7 (missing prototype via the genuine owner). `CL /Zs /W3` (`scratch/w3/c4013.txt`) reports two implicit declarations:
|
||||
`unit_start_running_blindly` (line 414) and `unit_is_speaking` (line 689). Their definitions are `units.c:3897`
|
||||
(`void unit_start_running_blindly(long unit_index)`; only a units.c-local prototype exists) and `unit_dialogue.c:389`
|
||||
(`boolean unit_is_speaking(long unit_index)`). No header declares either; `units.h` owns both prototype sections (UNITS.C and
|
||||
UNIT_DIALOGUE.C). January +0x1ea `test al,al` proves the boolean return; punpckhdq `units.h:557` declares `unit_is_speaking`
|
||||
right after `unit_notify_impulse_sound`.
|
||||
|
||||
Shadow-header method: `shadow_gate.py` compiles each unit inside a full copy of the `source/` headers (so every quoted include
|
||||
resolves in the shadow tree) and dumps per-function size/relocations/normalized sha. 76 units transitively include `units.h`.
|
||||
|
||||
| trial | units.h change | action_flee | 76-consumer deltas vs pristine |
|
||||
| --- | --- | --- | --- |
|
||||
| P | none | 12/1, perform = park base | - |
|
||||
| H1 | + `unit_is_speaking` only | 13/0 | perform -> target; speech_timers park load pair; `_physics_update_old` (non-exact); **`_unit_preprocess_node_orientations` EXACT -> residual** |
|
||||
| H2 | + both prototypes | **13/0** | **exactly two**: perform -> target; `_ai_communication_update_speech_timers` park flips to its second documented flag-neutral load order (672/43 `885fdb81966284ac`) |
|
||||
|
||||
Sum of strict-exact rows over the 76 units: P 2402 -> H2 2403, zero losses. H1 is rejected (declaration-count victim).
|
||||
|
||||
ORCHESTRATOR-PROPOSAL (exact diff `scratch/workers/w3_path_smoothing_actor_firing_position_etc/units_h_packet_H2.diff`, CRLF):
|
||||
|
||||
```c
|
||||
/* prototypes/UNITS.C, immediately before unit_stop_running_blindly */
|
||||
void unit_start_running_blindly(
|
||||
long unit_index);
|
||||
|
||||
/* prototypes/UNIT_DIALOGUE.C, immediately after unit_notify_impulse_sound */
|
||||
boolean unit_is_speaking(
|
||||
long unit_index);
|
||||
```
|
||||
|
||||
Consumers: 66 direct includers (`units_h_direct_includers.txt`), 76 compiled transitive consumers (`units_h_consumers.txt`).
|
||||
Same commit: unpark `_action_flee_perform` (864, no source change) and re-baseline the `_ai_communication_update_speech_timers`
|
||||
park base to `885fdb81966284acf5ba7138a4bbbd2221e7c61c89114fdd6f53b96ba89b81a0`. A full ninja plus stable sweep is required.
|
||||
|
||||
## Reopen criteria
|
||||
|
||||
- `_action_flee_perform`: met when the H2 packet lands (not the single-prototype variant).
|
||||
@@ -1,109 +0,0 @@
|
||||
# `action_flee.obj` position-helper packet (2026-09-09)
|
||||
|
||||
## Result
|
||||
|
||||
Two previously unwritten January functions are now strict COFF matches in a
|
||||
single, caller-connected translation-unit reconstruction:
|
||||
|
||||
| January owner | Recovered private name | Meaningful | Padded | Relocations | Normalized SHA-256 |
|
||||
| --- | --- | ---: | ---: | ---: | --- |
|
||||
| `_code_00003210` | `action_flee_find_flee_position` | 629 | 640 | 23 | `058dad92555bc68a3f7deb04f41c3b1995d70808b593c142c7f534383e18b0b7` |
|
||||
| `_code_000039e0` | `action_flee_at_flee_position` | 318 | 320 | 13 | `85c493abe1c07f9d923b165c98d0ec59098a6c21ef04a0954f8c5451507804fa` |
|
||||
|
||||
The packet therefore contributes **947 meaningful exact code bytes** and
|
||||
**960 padded exact bytes**. The focused gate reports 9 exact, 3 residual and
|
||||
1 unwritten function in `action_flee.obj`; the inherited baseline was 7 exact.
|
||||
No whole-object completion is claimed.
|
||||
|
||||
## Name and behavior evidence
|
||||
|
||||
The independent HaloCEA reconstructions at
|
||||
`research-cache/halocea-full-blobs-20260830/src/blam/ai/` recover the three
|
||||
private names and their caller relationships:
|
||||
|
||||
- `action_flee_find_flee_position.c`
|
||||
- `action_flee_current_position_exposed.c`
|
||||
- `action_flee_at_flee_position.c`
|
||||
- `action_flee_setup.c`
|
||||
- `action_flee_perform.c`
|
||||
|
||||
January remains the byte and branch-semantics authority. The first exact
|
||||
owner carries January's line-522 non-swarm assertion, selects and commits a
|
||||
cover/panic firing position, and computes an approach point through the real
|
||||
path subsystem. It uses `actor_get`, `actor_definition_get`, `prop_get` and
|
||||
`TAG_BLOCK_GET_ELEMENT`, plus declarations from the owning `ai.h`, `path.h`,
|
||||
and `actor_perception.h`; no raw datum/tag casts or local foreign prototypes
|
||||
were introduced.
|
||||
|
||||
The three ACTOR_PERCEPTION.C situation declarations live in the dedicated
|
||||
owner header. Their earlier placement in the middle of the heavily shared
|
||||
`actors.h` perturbed C2's declaration-position-sensitive allocation in
|
||||
`units.obj` and reopened one otherwise exact owner. Isolating the declarations
|
||||
keeps ActionFlee fully typed while preserving all 189 exact `units.obj`
|
||||
functions and the existing code generation of unrelated AI consumers.
|
||||
|
||||
The two previously undeclared PATH.C routines use an opt-in declaration block
|
||||
at the end of `path.h` for the same reason. The genuine `path_state_find`
|
||||
return type is corrected in the ordinary owner declaration, while the two new
|
||||
declarations are visible only to ActionFlee. This preserves the closer parked
|
||||
`encounter_update_respawn` schedule instead of silently degrading a fuzzy
|
||||
owner merely to expose unrelated declarations.
|
||||
|
||||
The second exact owner carries January's line-470 assertion, validates the
|
||||
current encounter firing position, honors the already-at-destination fast
|
||||
path, and compares the squared body distance against the actor's destination
|
||||
tolerance. January's final branches show that a tracked prop with line-of-
|
||||
sight value clear or occluded prevents this fallback arrival result; no prop,
|
||||
or a different line-of-sight state, permits it. This differs from the later
|
||||
HaloCEA lift's final polarity, so the donor was used only as a semantic/name
|
||||
map and the January branch behavior was preserved. The final boolean is
|
||||
normalized with the ordinary `result = !result; return result;` idiom; the
|
||||
open Marathon cseries source uses the same toggle-then-return spelling in
|
||||
`cseries.lib/macintosh_utilities.c`, so this is not an invented dependency or
|
||||
optimizer directive.
|
||||
|
||||
## Honest residuals retained with zero credit
|
||||
|
||||
The coherent callers needed to make the private static owners emit are kept as
|
||||
the best currently reviewed typed reconstructions, but they are not exact and
|
||||
receive zero matched-byte credit:
|
||||
|
||||
| Function | January | Candidate | Relocations (target/candidate) | Objdiff |
|
||||
| --- | ---: | ---: | ---: | ---: |
|
||||
| `action_flee_setup` | 272 padded / 265 meaningful | 256 padded | 12 / 12 | 80.265305% |
|
||||
| `action_flee_current_position_exposed` | 352 padded / 347 meaningful | 352 padded | 13 / 13 | 83.46342% |
|
||||
| `action_flee_perform` | 864 padded / 857 meaningful | 848 padded | 30 / 30 | 77.46595% |
|
||||
|
||||
Their normalized target/candidate SHA-256 pairs are respectively:
|
||||
|
||||
- setup: `1a415a0adece0dd541b62c1c9ada51604d58751e66d769d88619d76db5471d79` /
|
||||
`cfc7ace7bcb857227c8c0559c80681a4f9ff2b142fa9df3e57c59af75960a898`
|
||||
- current-position exposure: `498dc2c046073108d309d0057bb5fc0405a8112c5532e90ef7ec5e79f21d7708` /
|
||||
`bbfe7ce7c3bafd235c0528f0480f5836b1d5016ec27e364ef77db6381c616c60`
|
||||
- perform: `d62f05304574f88eefd7c025a452910d821e3986442777adcb223dc0d2085dc2` /
|
||||
`e4b2a3cecd2525f5989ea94abd238fd8cc687627248f91ba39f597fe4ae66f7e`
|
||||
|
||||
These are ordinary typed C with named constants and subsystem APIs. They
|
||||
contain no volatile/register forcing, pragma, assembly, raw offset,
|
||||
representation pun, fake dependency, undefined behavior or nonsensical
|
||||
branch. They should be revisited only with authoritative January source/local
|
||||
records or another natural same-compiler donor, not expression-order search.
|
||||
|
||||
## Verification boundary
|
||||
|
||||
The final PID-isolated campaign gate compiled only `source/ai/action_flee.c`,
|
||||
compared every target function, and rejected any emitted
|
||||
`_point_from_line3d` owner. The guard passed. Because the semantic symbol
|
||||
renames are part of this packet while the shared split object intentionally
|
||||
remained untouched, the focused gate used temporary in-memory aliases from
|
||||
the recovered private names to the old `_code_*` split labels. No Ninja,
|
||||
configure, shared build output or unrelated source file was touched.
|
||||
|
||||
The ordinary `real_math.h` distance expression also emits select-any fallback
|
||||
copies of `_distance_squared3d` (64 bytes), `_vector_from_points3d` (48 bytes)
|
||||
and `_magnitude_squared3d` (48 bytes). Each has zero relocations and exactly
|
||||
matches the corresponding January-selected owner in `action_alert.obj`
|
||||
(`f42fa39f289bfa50`, `905f56dbe4597d2b`, and `0d04579096eeab3a`
|
||||
respectively). They receive no target-owned or progress credit; this packet
|
||||
does not alter their ownership. No `_point_from_line3d` definition or
|
||||
reference is emitted.
|
||||
@@ -1,45 +0,0 @@
|
||||
# ActionFlee small-leaf reconciliation (2026-09-08)
|
||||
|
||||
## Result
|
||||
|
||||
This reconciliation admits three complete Fable-lane leaves into their real
|
||||
`action_flee.c` owner and moves their public declarations from the unrelated
|
||||
`actions.c` dispatcher into the closest associated header, `actions.h`.
|
||||
|
||||
| January owner | meaningful bytes | padded bytes | relocations | verdict |
|
||||
| --- | ---: | ---: | ---: | --- |
|
||||
| `_action_flee_flush_position_indices` | 39 | 48 | 2 | exact |
|
||||
| `_action_flee_modify_color` | 99 | 112 | 4 | exact |
|
||||
| `_action_flee_replace_prop` | 48 | 48 | 2 | exact |
|
||||
|
||||
The batch adds **186 meaningful / 208 padded exact code bytes** and three
|
||||
strict functions. The two inherited exact ActionFlee owners remain exact.
|
||||
|
||||
## Source and ownership review
|
||||
|
||||
The implementations use the existing typed `actor_get` accessor, the genuine
|
||||
`flee_state_data` fields, `NONE`, project booleans, and the canonical ARGB
|
||||
color owners. Parameters remain one per line and every void body ends with an
|
||||
explicit `return;`. No inline control, assembly, raw offset, address-derived
|
||||
name, fabricated dependency, or manual bit logic is introduced.
|
||||
|
||||
The declarations belong to `actions.h` because this translation unit has no
|
||||
dedicated header. All ActionFlee declarations now live there, including the
|
||||
setup/dispatch callbacks and `action_flee_blind_panic`; their duplicate local
|
||||
declarations were removed from `actions.c` and `actor_type_grunt.c` without
|
||||
changing either consumer's code owners.
|
||||
|
||||
## Focused evidence
|
||||
|
||||
The canonical source gate reports `5 exact / 0 residual / 8 unwritten` for
|
||||
`action_flee.obj`; `actions.obj` remains `58 exact / 5 residual / 0 unwritten`.
|
||||
Both gates reject any emitted `_point_from_line3d`, and the changed-file
|
||||
fake-match scan reports zero findings. The packet author also compared all 22
|
||||
other initially compilable `actions.h` consumers without a count change; the
|
||||
enclosing canonical build compiles the complete consumer set. The separate
|
||||
`ai_debug.c` Path-interface repair receives no ActionFlee proof or credit.
|
||||
|
||||
The full-build, rename-stable sweep, park validation, admission audit and test
|
||||
suite are recorded in the enclosing reconciliation batch. These three bodies
|
||||
receive exact credit only if that global admission gate reports no inherited
|
||||
loss.
|
||||
@@ -1,189 +0,0 @@
|
||||
# `action_flee.obj` update semantic and owner boundary, 2026-09-05
|
||||
|
||||
## Result
|
||||
|
||||
`action_flee_update` is **withheld**. This review admits neither exact nor
|
||||
fuzzy code and creates no park. The current production object remains at its
|
||||
published two strict functions; the attempted update remains unwritten.
|
||||
|
||||
Two independent blockers were demonstrated:
|
||||
|
||||
1. The required public-API ownership repair changes two inherited strict Race
|
||||
functions and the existing AI speech-timer park in a full 84-object header
|
||||
trial. The entire four-file API packet was restored; there is no
|
||||
caller-local declaration or header-position workaround.
|
||||
2. The first natural 160-byte body writes the positive-panic timestamp to the
|
||||
wrong, adjacent semantic member. January writes actor `+0x39C`; the
|
||||
candidate writes `+0x398`. This is not an ordinary scheduling residual and
|
||||
is not eligible for a fuzzy park.
|
||||
|
||||
The member discrepancy is now resolved by a complete neighboring-use census:
|
||||
the existing layout is correct. Actor `+0x398` is
|
||||
`emotions.last_flee_failed_time`, while `+0x39C` is
|
||||
`emotions.flee_with_friends_disable_time`. A new source manifest containing
|
||||
only that semantic member correction is preserved pending a future genuine
|
||||
API context. It was deliberately not compiled against restored, incorrectly
|
||||
owned declarations.
|
||||
|
||||
## January behavior and ABI
|
||||
|
||||
The authoritative January `_action_flee_update` is 152 meaningful / 160
|
||||
padded bytes, has four relocations, and contains 54 decoded instructions.
|
||||
Its normalized SHA-256 is
|
||||
`c5e5c557ca1dc9c70ea3fe4dbfff11451fc6a5b7a1b71921f839386588fbe2d8`.
|
||||
Its call/data relocations, in order, are `_actor_data`, `_datum_get`,
|
||||
`_unit_start_running_blindly`, and `_game_time_get`.
|
||||
|
||||
The target establishes the following source contract:
|
||||
|
||||
- `actor_index` is a complete 32-bit datum handle. The prologue loads the
|
||||
full dword argument and passes it to `datum_get`; the HCEA donor's
|
||||
`uint16_t` parameter is not the January ABI.
|
||||
- `actor->meta.unit_index` at actor `+0x18` is also consumed and passed as a
|
||||
complete 32-bit handle.
|
||||
- `forced_flee_ticks` at `+0x9C`, `flee_stationary_ticks` at `+0x9E`, and
|
||||
`panic_type` at `+0xA8` are signed 16-bit values.
|
||||
- `flee_timer` at `+0xB4` increments every call with 32-bit machine wrapping.
|
||||
- A positive forced-flee countdown decrements once. A positive stationary
|
||||
countdown decrements once; only its `1 -> 0` transition can start blind
|
||||
running, and only when the unit is not `NONE` and the signed panic value is
|
||||
in the inclusive `[9, 12]` interval.
|
||||
- The blind-running decision naturally calls the already strict
|
||||
`action_flee_blind_panic(short)` source helper. The compiler may inline its
|
||||
range test; the helper must not be manually expanded or artificially
|
||||
retained.
|
||||
- Independently of the unit/countdown path, any signed `panic_type > 0`
|
||||
calls `game_time_get`, adds 750 ticks (`25*TICKS_PER_SECOND`) modulo 32
|
||||
bits, and stores the result at actor `+0x39C`.
|
||||
- When both calls occur, `_unit_start_running_blindly` precedes
|
||||
`_game_time_get`. The function returns `void` and preserves its callee-saved
|
||||
state and stack.
|
||||
|
||||
## The adjacent fields are not a missing-layout gap
|
||||
|
||||
Three independent January-backed uses distinguish the two adjacent dwords:
|
||||
|
||||
- In `_action_flee_perform`, after setting the flee state's
|
||||
`unable_to_flee` byte, the target calls `_game_time_get` and at function
|
||||
offset `+0x1C3` stores EAX to actor `+0x398`.
|
||||
- `_actor_action_handle_panic_transition` tests actor `+0x398` against
|
||||
`NONE`, calls `_game_time_get`, reloads `+0x398`, adds seven ticks, and
|
||||
compares it with the current time. Current source names that value
|
||||
`last_flee_failed_time`.
|
||||
- The strict January/canonical `_actor_stimulus_prop_fleeing` calls
|
||||
`_game_time_get` and at function offset `+0x58` compares it with actor
|
||||
`+0x39C`. Its natural typed source names that value
|
||||
`flee_with_friends_disable_time`; the function is strict exact at
|
||||
263 meaningful / 272 padded bytes and 14 relocations, normalized SHA-256
|
||||
`13df393dee019d54339f963e17edd5d85610d11ce48fe5c2e357240b22f65da1`.
|
||||
|
||||
The canonical `actor_emotion_data` already declares those members in that
|
||||
order. Its base is actor `+0x350`, so relative offsets `+0x48` and `+0x4C`
|
||||
produce the observed actor offsets `+0x398` and `+0x39C`. The HCEA
|
||||
`actor_emotion_data.h` independently corroborates both names and offsets, but
|
||||
its `action_flee_update.c` incorrectly selects `last_flee_failed_time` and is
|
||||
not authoritative. The extracted January PDB census contains no member-level
|
||||
type record for these fields, so no direct PDB-name claim is made.
|
||||
|
||||
The behavior is also coherent: a live positive panic refreshes a 25-second
|
||||
cooldown that suppresses group/friend-flee propagation, while a failed flee
|
||||
attempt records its separate, short-lived failure time at `+0x398`. No
|
||||
padding, field insertion, or four-byte schema shift is proposed.
|
||||
|
||||
## First natural body and executable behavior review
|
||||
|
||||
The first natural source used `actor_get`, the existing typed flee-state and
|
||||
emotion layouts, the already strict blind-panic helper, and owner APIs. Its
|
||||
focused gate was `2 exact / 1 residual / 10 unwritten`; both inherited strict
|
||||
functions and the hard `_point_from_line3d` guard were preserved. The new
|
||||
function is also 160 bytes with four relocations and 54 instructions. Its
|
||||
normalized SHA-256 is
|
||||
`6e9a8d4d811187492ebf30f9a1942589321ce1e5beedf2c30045564be563bb28`.
|
||||
|
||||
Aligned disassembly finds exactly one instruction difference:
|
||||
|
||||
```text
|
||||
target +0x8F mov dword ptr [esi + 0x39c], eax
|
||||
candidate +0x8F mov dword ptr [esi + 0x398], eax
|
||||
```
|
||||
|
||||
The bounded Unicorn harness executes only `_action_flee_update` and stubs
|
||||
only its three genuine call boundaries: `_datum_get`,
|
||||
`_unit_start_running_blindly`, and `_game_time_get`. It verifies exact API
|
||||
arguments, event order, all actor bytes outside target-written fields,
|
||||
callee-saved registers, and stack balance. Its 47 cases cover:
|
||||
|
||||
- signed countdown boundaries `-32768, -1, 0, 1, 2, 32767`;
|
||||
- `NONE` and full-width `0x89ABCDEF` unit handles;
|
||||
- panic boundaries `-32768, -1, 0, 1, 8, 9, 10, 12, 13, 32767`;
|
||||
- actor handles `0x00000007`, `0x12340007`, and `0xFFFF0007`;
|
||||
- zero, sign-boundary, and all-one flee counters; and
|
||||
- timestamp addition across 32-bit wrap.
|
||||
|
||||
The frozen January target passes **47/47**. The first candidate passes
|
||||
**27/47** and fails exactly the 20 cases with positive panic. Every failure
|
||||
has the same adjacent-field difference spanning actor bytes
|
||||
`[0x398, 0x3A0)`: the candidate overwrites `last_flee_failed_time` and leaves
|
||||
`flee_with_friends_disable_time` unchanged. Countdown behavior, complete
|
||||
handles, calls, call order, and counter behavior agree in the remaining
|
||||
observations. This is direct behavioral rejection of the candidate, not a
|
||||
request to adapt the expected offset.
|
||||
|
||||
## Required owner-header repair and failed blast
|
||||
|
||||
A source-faithful production packet requires these ownership changes as one
|
||||
coherent boundary:
|
||||
|
||||
- declare `void action_flee_update(long actor_index)` in `actions.h` and
|
||||
remove its consumer-local declaration from `actions.c`;
|
||||
- declare `void unit_start_running_blindly(long unit_index)` in `units.h`
|
||||
and remove its owner-C local declaration from `units.c`; and
|
||||
- include `game/game.h` from `action_flee.c` for the already owned
|
||||
`game_time_get` API.
|
||||
|
||||
Root tested the pure owner-header migration across the complete 84-object
|
||||
consumer union before admitting the body. It materially changed
|
||||
`_race_touch_flag` (336 padded bytes) and
|
||||
`_race_engine_player_update` (160 padded bytes), losing both inherited Race
|
||||
stricts. It also changed the normalized body of the existing
|
||||
`_ai_communication_update_speech_timers` park. The packet was therefore
|
||||
withheld without header-position permutations, local-prototype fallback, or
|
||||
shim headers.
|
||||
|
||||
After restoring all four API files, the full build returned to 6,217 strict
|
||||
owners out of 8,245 with zero losses, and all 281 parks validated. Production
|
||||
`action_flee.c`, the owner headers, and configuration remain unchanged by
|
||||
this review.
|
||||
|
||||
## Frozen evidence
|
||||
|
||||
| Artifact | SHA-256 | Disposition |
|
||||
| --- | --- | --- |
|
||||
| `scratch/action-flee-update-target-frozen-20260905.obj` | `5D6E667103C4B42824A5E1C69FB047860A60D901EDA36153162CF19672EFF59E` | January target |
|
||||
| `scratch/action-flee-update-natural-api-trial-20260905.obj` | `FA607D970E3E97D39519086C1FFA09008E98659211C35E2D2BF760D485E8B6D9` | rejected wrong-member candidate |
|
||||
| `scratch/action_flee_update_natural_20260905.edits.json` | `2D9D0F48A831E2B2E9FF8EA1D1B8C1E6C2BAA797C79CDECA8CB8CD5B241B3197` | immutable first-source manifest |
|
||||
| `scratch/action_flee_update_semantic_corrected_pending_20260905.edits.json` | `14D98FCD9964F932CDF92AB99364B974EEE009E4B75CB0B6A97C0577F980C58E` | one-member source correction, intentionally uncompiled |
|
||||
| `scratch/action_flee_update_behavior_review_20260905.py` | `927D2B29FAF1A400B7429F60FE24146E8DC520CC71D617C156FD45E76DDAE1C2` | bounded behavior harness |
|
||||
| `scratch/action-flee-update-target-behavior-reviewed-20260905.json` | `910C06F6630F38AC25B3B2E2F3A013BDC8CC577C717235515C98776FF620DE69` | target 47/47 pass |
|
||||
| `scratch/action-flee-update-candidate-behavior-reviewed-20260905.json` | `EB6EC2F6A66739A828B6C2A2DCA431A9185EEF45015B427930DB1AB8CFF0D4C0` | candidate 27/47 pass, 20 semantic failures |
|
||||
| `scratch/action-flee-api-failure-summary-20260905.json` | `6C68F7B76ACC6120F8D50A121FEAA206918763BCE5EEE83B69BACDEF168A88BD` | 84-object owner-header failure census |
|
||||
| `scratch/action-flee-api-restored-20260905.json` | `5EF39E7AD811893F6E1FFAA2F46F960D06592AEDB144E958FF646E386B72CFB7` | restored stable census |
|
||||
| `scratch/action-flee-api-parks-restored-20260905.json` | `92ED21DB874053C53684CDD519F70A2D1ACAAD96F76F9E0E8E0CD866879DB739` | restored 281-park validation |
|
||||
| `scratch/actor-stimulus-prop-fleeing-canonical-20260904.obj` | `2FE9919CFE7DF2B7E8A7C6A895EB2DEECBA75FF12856BEB162E6377F1B731764` | strict `+0x39C` consumer |
|
||||
|
||||
Harness reproduction uses frozen objects only:
|
||||
|
||||
```text
|
||||
python scratch/action_flee_update_behavior_review_20260905.py scratch/action-flee-update-target-frozen-20260905.obj --output scratch/action-flee-update-target-behavior-reviewed-20260905.json
|
||||
python scratch/action_flee_update_behavior_review_20260905.py scratch/action-flee-update-natural-api-trial-20260905.obj --output scratch/action-flee-update-candidate-behavior-reviewed-20260905.json
|
||||
```
|
||||
|
||||
## Reopen condition
|
||||
|
||||
Reopen only as a coherent owner-header trial after the Race and speech-timer
|
||||
collateral can be reconciled by independently authenticated source/API
|
||||
evidence. At that point compile the preserved corrected manifest once in the
|
||||
genuine header context and repeat the behavior, full owner, no-point, park,
|
||||
and whole-tree stable checks. Do not patch the old object, shift the actor
|
||||
layout, restore caller-local externs, permute declarations, or classify the
|
||||
wrong-member candidate as fuzzy progress.
|
||||
@@ -1,152 +0,0 @@
|
||||
# ActionObey public API and structure-flush leaf: independent admission review
|
||||
|
||||
## Conclusion
|
||||
|
||||
The frozen public-API owner packet is **admission-safe and runtime-neutral**. The structure-index flush leaf is also technically sound: it adds exactly one genuine public function owner, is a strict all-section match to January, preserves every inherited section, has the correct 32-bit C ABI and owner metadata, and matches January behavior in 1,024 bounded executions. It adds **46 meaningful / 48 padded code bytes** and no data credit.
|
||||
|
||||
One provenance caveat remains for the root's policy decision. The body is typed, idiomatic, semantically corroborated, and contains no byte-forcing construct, but the Fable report explicitly says its exact source shape corrected the earlier 2026-08-21 miss by introducing the local `state_data` pointer. It therefore must not be described as an independently natural first candidate. If admission requires first-shot provenance rather than an authenticated exact reconstruction, this leaf needs explicit adjudication; its object, ABI, runtime, API-owner, and no-surplus evidence otherwise pass.
|
||||
|
||||
This review does not cover the parallel shared swarm/enum schema packet. No production, donor, build, configuration, park, or frozen object was changed, and no compile or gate was run.
|
||||
|
||||
## Source packet and owner boundary
|
||||
|
||||
There is no `action_obey.h`. `source/ai/actions.h` is the genuine narrow owner because it already owns `action_specification`, all obey control/state records, the other action-family public declarations, and an explicit `prototypes/ACTION_OBEY.C` section. The frozen API change adds these nine target-public declarations there:
|
||||
|
||||
```c
|
||||
boolean action_obey_command_list_setup(
|
||||
long actor_index,
|
||||
short command_list_index,
|
||||
struct obey_state_data *state_data);
|
||||
void action_obey_flush_command_indices(
|
||||
long actor_index);
|
||||
void action_obey_flush_structure_indices(
|
||||
long actor_index);
|
||||
void action_obey_advance_command_list(
|
||||
long actor_index);
|
||||
void action_obey_begin(
|
||||
long actor_index);
|
||||
boolean action_obey_perform(
|
||||
long actor_index);
|
||||
void action_obey_update(
|
||||
long actor_index);
|
||||
void action_obey_control(
|
||||
long actor_index);
|
||||
void action_obey_end(
|
||||
long actor_index);
|
||||
```
|
||||
|
||||
`action_obey_describe_command` was already present in that owner section. Every added symbol is an external January function (`storage=2`, `type=0x20`, `value=0`, NODUP function COMDAT). The signatures agree with the existing consumer-local declarations, the `action_specification` callbacks, January's ordinary 32-bit stack accesses, and the retained HCEA semantics. In particular, `action_obey_command_list_setup(long, short, obey_state_data *)` preserves the pre-existing `actions.c` declaration exactly.
|
||||
|
||||
The paired cleanup removes from `actions.c` only the now-owned local declarations for `action_obey_command_list_setup` and the five action-table callbacks (`begin`, `perform`, `update`, `control`, `end`). It later removes the local `actor_action_change` declaration from `action_obey.c`; `actions.h` already owns that exact three-argument declaration. Moving declarations does not create a definition, helper, or alternate ABI.
|
||||
|
||||
The three no-current-cross-TU-call declarations (`flush_command_indices`, `flush_structure_indices`, and `advance_command_list`) are not synthetic helpers: all three are genuine external January owners. Later/HCEA callers also corroborate their public nature. `perform` and `control` are presently unwritten in canonical, but `actions.c` genuinely references both from the obey action table; their prototypes are necessary public contracts rather than promises invented for this leaf.
|
||||
|
||||
The frozen public API source hashes are:
|
||||
|
||||
- before: `actions.h` `f62df99f9ad20305ed01ebd09e120378aa513874dc3b990c2a07775a41e98086`, `actions.c` `3dbb2e77c2f4fd40cc0376589b9d3024f47f7a47d6e8375d8b0e9a3a616e44a2`;
|
||||
- after: `actions.h` `962973471e872cf3f159ef06d1f8209c9a962a8fae5cac8bbb18e2e7d21146ac`, `actions.c` `f6347eb2573a36f12cf0c9253da66504441b8743269e8847fd3866770571d7ec`.
|
||||
|
||||
At review time the current `actions.c` still has the frozen after hash, while `actions.h` has subsequently changed to `ea1bec48dfcc5bdad4dc01137e8c9d4a1f6aa878ee6f3eae4d0ef13e64aee62` from the root's parallel schema work. The nine API declarations themselves remain textually unchanged. This report makes no claim about that later schema content.
|
||||
|
||||
## Public API dependent audit
|
||||
|
||||
The capture script resolved all real `actions.h` dependencies from the Ninja graph and froze 47 objects. The before and after unit lists are identical. Independent review of the runtime summary found:
|
||||
|
||||
- 47/47 units preserved;
|
||||
- 3,079 runtime sections unchanged;
|
||||
- 54 changes classified solely as compiler-local label spelling across 22 units;
|
||||
- zero review-required units;
|
||||
- zero runtime sections added, lost, or genuinely changed;
|
||||
- zero genuine function-owner changes and zero new helpers;
|
||||
- zero COMMON additions/removals;
|
||||
- zero new `_point_from_line3d` emission or reference.
|
||||
|
||||
The full stable verdict maps are byte-identical: both contain 8,245 entries and share SHA-256 `223b39e9a64198e10ff6dab9fe24a92b1d715b87e385c9389fee4188d6a0f458`. The captured park census is 284 active, 0 stale, 0 invalid. Thus the API move has no inherited exact/residual loss and no ordinary-link owner side effect.
|
||||
|
||||
Primary frozen files:
|
||||
|
||||
- `scratch/action-obey-public-api-before-20260905.json` — SHA-256 `22082d37d81366a681520949d9502107f7ea43b8e185f29936643cd07c89d0d5`;
|
||||
- `scratch/action-obey-public-api-after-20260905.json` — SHA-256 `49d6f456321f119a67d25ac7324d82b4fc282d43cf1e86044f4a342e43284f65`;
|
||||
- `scratch/action-obey-public-api-runtime-audit-20260905/summary.json` — SHA-256 `6f473b63e0918f9f085c664dbccebcac2c28668cfc2196a95e5a510504f70e9e`;
|
||||
- `scratch/action-obey-public-api-parks-20260905.json` — SHA-256 `6c212dbc1d83de169bccde32a1c1ed3acc281d998bc8ec42ebe9e1b37e850cfa`.
|
||||
|
||||
## Leaf body and source authenticity
|
||||
|
||||
The current leaf is:
|
||||
|
||||
```c
|
||||
void action_obey_flush_structure_indices(
|
||||
long actor_index)
|
||||
{
|
||||
struct actor_datum *actor = actor_get(actor_index);
|
||||
struct obey_state_data *state_data = &actor->state.action_data.obey;
|
||||
|
||||
if (state_data->complex_control.destination_valid)
|
||||
{
|
||||
state_data->complex_control.destination_surface_index = NONE;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
This is a genuine typed implementation. It uses the owning records, an existing typed actor accessor, the named valid/surface fields, and the repository's `NONE` constant. It contains no raw offset, cast reconstruction, aliasing trick, inline/optimizer directive, synthetic anchor, or surplus wrapper.
|
||||
|
||||
Three independent sources support the behavior:
|
||||
|
||||
1. January PC code loads the full dword argument from `[ebp+8]`, passes that full handle with `_actor_data` to `_datum_get`, reads the byte at actor `+0xCC`, materializes the obey-state base at actor `+0x9C`, and conditionally stores `0xFFFFFFFF` at state `+0x40` (actor `+0xDC`).
|
||||
2. The retained HCEA function tests `obey.complex_control.destination_valid` and sets `destination_surface_index=-1` on true.
|
||||
3. The adjacent accepted canonical obey wrappers use the same `actor` then `state_data` local source pattern.
|
||||
|
||||
The HCEA extraction spells this one function's actor parameter `uint16_t`, unlike the surrounding `int` functions. That later-platform/decompiler spelling is not PC ABI authority. January's dword load, the target relocation/call sequence, the callback-family contract, and the runtime harness's untruncated handle prove canonical `long` is correct.
|
||||
|
||||
The caveat is derivation history, not source semantics. The 2026-08-21 natural batch produced a different 46/48 candidate hash and removed the miss after one attempt. Fable later recorded that the exact body added the `state_data` pointer missing from that attempt. Because it explicitly consumed the previous mismatch boundary, this implementation cannot inherit the earlier ledger's first-shot label even though the resulting ordinary C body is authentic in form.
|
||||
|
||||
## Exact object and owner evidence
|
||||
|
||||
January target object SHA-256 is `0e4f889a35b97c44f6ae91e4906b547bd64f2ff12b9f399e02b46f02b69633fb`. The frozen owner-clean candidate object SHA-256 is `543ef02661eafabe28197ce23ddd345fdfb4818d543017219ce933d56562da0e`.
|
||||
|
||||
For `_action_obey_flush_structure_indices`, target and candidate agree on:
|
||||
|
||||
- 46 meaningful bytes and a 48-byte padded section (two terminal NOPs);
|
||||
- normalized SHA-256 `9f0facf2a5e64545b5b323119ea1ce6c45813a307bf0fb256308aab64fe0db82`;
|
||||
- relocation `+0x08`, `IMAGE_REL_I386_DIR32`, to `_actor_data`;
|
||||
- relocation `+0x0F`, `IMAGE_REL_I386_REL32`, to `_datum_get`;
|
||||
- `.text` flags `0x60501020`, external storage 2, function type 32, value 0, COMDAT selection 1.
|
||||
|
||||
The first leaf comparison (before to after) adds exactly one runtime section and one genuine function owner. It changes no inherited runtime section, adds/removes no COMMON, emits no forbidden point helper, and has no debug delta. The later owner cleanup (removing the redundant `actor_action_change` local declaration) preserves all 12 runtime sections and every program symbol identity; it creates no new helper or owner.
|
||||
|
||||
Frozen leaf chain:
|
||||
|
||||
- before manifest `ee343e4c289c0b81eaa4972b030f1f1db83a150d1cd13096a5393e82c3f0c91e` / object `10ee91a816e424347da9cc3ccf6c820e6f4b7f4f4aba09d303eef26a0b547c5f`;
|
||||
- body-after manifest `928b2bde2a3aa4c568d726ff87457c2ff91ad64f47f0b8d22aa8fdc9c47ae426` / object `9edaf5bafdd56b1ab3864f7b3a777e6b8ad688084571346efc2b1b0d6429a531`;
|
||||
- owner-clean manifest `d8435f09c9c20d28562d4c62b5b587a57df19a99c2961c6d3255313e6ee3f581` / object `543ef02661eafabe28197ce23ddd345fdfb4818d543017219ce933d56562da0e`.
|
||||
|
||||
The isolated replay object (`69ae82ce4432cbe0df25eeb0d4e5912e16e19c8527a3aef7e645d31fac58d238`) defines the nine inherited exact functions plus this leaf—ten function owners total—and no unexpected code owner. The full before/after runtime report identifies only the new leaf; the owner-clean comparison is completely unchanged.
|
||||
|
||||
## Runtime differential
|
||||
|
||||
The final scratch runtime harness tests target, owner-clean actual, and isolated objects over all 256 possible `destination_valid` byte representations and four prior surface values (`0`, `17`, `0x80000000`, `0xFFFFFFFF`), or 1,024 cases per object. All three produce trace SHA-256 `999e2273e77f3347e5871616830525f72c861071faf31f8e1757762f2767becd`.
|
||||
|
||||
It also verifies:
|
||||
|
||||
- one and only one `_datum_get(_actor_data, actor_index)` call;
|
||||
- the full 32-bit handle reaches the accessor;
|
||||
- the surface changes to `NONE` iff the valid byte is nonzero;
|
||||
- no other modeled actor byte changes;
|
||||
- callee-saved registers, stack cleanup, and direction flag behavior;
|
||||
- exact target section and owner metadata before execution.
|
||||
|
||||
The stated limit is appropriate: this models a valid actor handle and the `datum_get` contract; it is not a whole actor subsystem or image-link test. There is no uncovered input branch inside this leaf once those API preconditions hold.
|
||||
|
||||
Evidence:
|
||||
|
||||
- `scratch/action-obey-structure-leaf-owned-runtime-20260905.json` — SHA-256 `65e17c98c27a46eb49b0e25e92e95984d7d9b291e9b8dc11ec60f80d632b3752`;
|
||||
- runtime script SHA-256 `d686a0c4c2251909cc6d7d4428091f318f2f867c35841c09a5441a6ae034b704`;
|
||||
- owner-clean all-section summary SHA-256 `97a66ae9554056837a796f433621a966546b8ade2f21fdde4da1da4d9ceb5bf6`.
|
||||
|
||||
## Accounting and admission statement
|
||||
|
||||
Before this leaf, canonical `action_obey.obj` had 9/27 exact functions and 439 meaningful / 480 padded code bytes. This packet advances it to **10/27 exact**, **485 meaningful**, and **528 padded** code bytes. The incremental claim is exactly one function and **46 meaningful / 48 padded bytes**. It claims no `.rdata`, `.data`, BSS, COMMON, or other data owner.
|
||||
|
||||
Technical verdict: **PASS** for API ownership, exactness, ABI, runtime semantics, inherited-owner preservation, and accounting. Provenance verdict: **review required only for the “natural first candidate” label**; the frozen record establishes that it is a later exact correction. Do not roll this caveat into the separate shared-schema trial, and do not use this leaf as blanket precedent for the larger Fable ActionObey donor cluster.
|
||||
@@ -1,98 +0,0 @@
|
||||
# ActionObey command-owner trial: rejected and restored
|
||||
|
||||
Date: 2026-09-05. Baseline: `c32247e7651d680dcd133d72b2fbf4e8009cc124`.
|
||||
|
||||
## Disposition
|
||||
|
||||
No source or byte credit from this shared-header trial is retained. Its full
|
||||
12-file source delta was reversed with a scoped patch; no checkout/reset/clean
|
||||
or donor edit was used. The completed earlier shared swarm/biped/API packet
|
||||
and structure-cache leaf remain intact.
|
||||
|
||||
The trial moved actor fire-target/combat-status enums to `actors.h`, moved
|
||||
the unit animation impulse domain to `units.h`, and put command modifier
|
||||
domains plus complete animation/script/recording reference records in
|
||||
`ai_scenario_definitions.h`. Corresponding local shadows in nine C files
|
||||
were removed. Datum field types and layouts were not changed; vehicle seat
|
||||
desire ownership and Units implementation/private-name cleanup were not added.
|
||||
|
||||
The source proposal's first patch accidentally contained a redundant
|
||||
`struct ai_command_definition;` forward declaration. This was removed as
|
||||
an editing correction before the measured after snapshot. It was not
|
||||
retained or searched as a compiler-order device.
|
||||
|
||||
## Measured failure
|
||||
|
||||
Actual Ninja dependencies identified **86** consuming base objects. The
|
||||
complete strict sweep fell **6,233 -> 6,232**: the previously exact
|
||||
`source/units/units::_unit_preprocess_node_orientations`, 1,920 padded bytes,
|
||||
became residual. The full owner comparison found:
|
||||
|
||||
- 6,270 unchanged runtime sections;
|
||||
- 84 changes restricted to compiler-local label spelling;
|
||||
- one changed runtime owner, the Units function above;
|
||||
- no added forbidden `_point_from_line3d` definition/reference.
|
||||
|
||||
The trial was rejected rather than exchanging inherited exact progress for
|
||||
new dependency coverage. No header ordering, source spelling, flags, or
|
||||
local facade variants were searched to rescue it.
|
||||
|
||||
## Restoration proof
|
||||
|
||||
The restored full sweep is **6,233 exact**, zero gains and zero losses.
|
||||
All **6,355** runtime sections across the 86 affected objects compare
|
||||
unchanged after restoration. Units is back to 189/189 exact.
|
||||
|
||||
The first restored capture correctly refused when its Ninja-dependency
|
||||
database hash changed during enumeration. No compiler processes remained;
|
||||
the next unchanged-state capture succeeded. The failed attempt wrote no
|
||||
manifest or object snapshot and was not accepted as evidence.
|
||||
|
||||
Frozen evidence paths, relative to the canonical repository:
|
||||
|
||||
- `scratch/action_obey_command_owners_capture_20260905.py`
|
||||
- `scratch/action-obey-command-owners-before-20260905.json`,
|
||||
SHA-256 `34c077c0b3cbe43476e5e9dadc1a24fc22d29c462db23976b8ae1b8a45d8702d`
|
||||
- `scratch/action-obey-command-owners-after-20260905.json`,
|
||||
SHA-256 `090874e7e335ae137a823e4de032de6122ca89bee8860bfd397fec166a08a404`
|
||||
- `scratch/action-obey-command-owners-restored-20260905.json`,
|
||||
SHA-256 `23e6ff746d10fa75f5c23449f16903138281cac98ca62b54da20053adcd4523a`
|
||||
- corresponding `*-stable-before/after/restored-20260905.json` snapshots;
|
||||
- `scratch/action-obey-command-owners-runtime-20260905/summary.json`;
|
||||
- `scratch/action-obey-command-owners-restored-runtime-20260905/summary.json`;
|
||||
- measured corrected-build and restored-build logs under the same prefix.
|
||||
|
||||
The capture folders preserve every proposed/restored source file and all 86
|
||||
actual objects. This is a rejected trial, not proof that every source-authentic
|
||||
owner reconstruction must fail.
|
||||
|
||||
## Corrections discovered during independent prerequisite review
|
||||
|
||||
The complete private `action_obey_command_begin` and
|
||||
`action_obey_command_perform` proposals remain scratch-only and uncompiled.
|
||||
Later direct PDB checks refined the initial proposed owner declarations:
|
||||
|
||||
- The true wait names are `_ai_atom_wait_modifier_alerted`,
|
||||
`_ai_atom_wait_modifier_visible_enemy`, and
|
||||
`_ai_atom_wait_modifier_told_to_advance`, values 0..2. The adjacent
|
||||
"always" literal belongs to loop modifier zero, not a fourth wait value.
|
||||
January's out-of-domain wait behavior still returns true.
|
||||
- PDB records authenticate all fourteen unit animation impulse names and
|
||||
the full three scenario reference layouts. Their `unused` fields are
|
||||
genuine records, not fabricated opaque prefixes.
|
||||
- PDB constants belong to unnamed enums. Descriptive named enum tags in the
|
||||
initial proposal were reconstructions, not recovered source names.
|
||||
- The fire-target terminal is DB-spelled `number_of_actor_fire_targets`;
|
||||
the previously suggested uppercase spelling was a style reconstruction.
|
||||
- Directly named crouch/targeting/initiative/die modifier constants can
|
||||
replace the private begin proposal's remaining raw boolean-valued literals
|
||||
when the proper shared owner is integrated.
|
||||
|
||||
These corrections are preserved in the prerequisite inventory and do not
|
||||
authorize a definition-order or equivalent-spelling search. A future coherent
|
||||
owner packet must use the refined evidence, preserve actual dependent
|
||||
objects, and keep private functions private. No consumer-local enum/type/
|
||||
prototype shadow or fake external private ABI is an acceptable workaround.
|
||||
|
||||
The independently acceptable smaller callback graph does not need this
|
||||
failed owner packet; it is tracked separately.
|
||||
@@ -1,176 +0,0 @@
|
||||
# `action_obey.obj`: inline math wrapper trio (2026-08-26)
|
||||
|
||||
## Outcome
|
||||
|
||||
Three ordinary inline math wrappers are newly strict-exact:
|
||||
|
||||
- `_vector_from_points2d`;
|
||||
- `_cross_product3d`;
|
||||
- `_negate_vector3d`.
|
||||
|
||||
The wave adds three exact functions and 122 meaningful code bytes.
|
||||
`action_obey.obj` advances from 6/27 to 9/27 exact functions and from 317 to
|
||||
439 matched meaningful code bytes. It remains incomplete; no completion
|
||||
label, semantic exception, adjudication, data credit, or comparator waiver was
|
||||
added.
|
||||
|
||||
Source commit:
|
||||
|
||||
- `ef95dd016320fed49b3945c7443513b33bd005fe`
|
||||
(`Match action obey inline math wrappers`).
|
||||
|
||||
## Frozen evidence
|
||||
|
||||
The untouched translation unit was frozen at commit
|
||||
`f529d037bc66823234e5e7a48bfdda08563b1ae8` in:
|
||||
|
||||
- `build/audit/action_obey_inline_math_baseline_20260826.json`;
|
||||
- manifest SHA-256
|
||||
`6b18cb311648b730e7264cd328aaffe96cc12e534c256011ab9174adb54dca3a`.
|
||||
|
||||
The target functions have these authenticated January fingerprints:
|
||||
|
||||
| Function | Meaningful / padded bytes | Relocations | Normalized SHA-256 |
|
||||
| --- | ---: | ---: | --- |
|
||||
| `_vector_from_points2d` | 29 / 32 | 0 | `5c9ee61634eac376cfc65890719accfeb6e0f5db37c55ab93b4da88bcbfe4f80` |
|
||||
| `_cross_product3d` | 60 / 64 | 0 | `660da515fee7a623e6230a78b71749517ee5ad376db4126e5c8fe79414d2623a` |
|
||||
| `_negate_vector3d` | 33 / 48 | 0 | `3265a51c2e64caa7a94fc32386ad62d6a774c929993624a9e83f35fbc2f2afcd` |
|
||||
|
||||
This was a same-name, same-ABI transfer rather than a masked-shape guess.
|
||||
Current rebuilt objects already emit each exact function from the canonical
|
||||
inline bodies in `source/math/real_math.h`. Representative accepted donors
|
||||
include:
|
||||
|
||||
- `vector_from_points2d`: `real_math.obj`, `collision_bsp.obj`, and
|
||||
`collision_features.obj`;
|
||||
- `cross_product3d`: `actor_type_infection.obj`, `ai_debug.obj`,
|
||||
`players.obj`, `matrix_math.obj`, `random_math.obj`, `real_math.obj`,
|
||||
`objects.obj`, `bsp3d.obj`, and `collision_bsp.obj`;
|
||||
- `negate_vector3d`: `players.obj`, `real_math.obj`, `models.obj`,
|
||||
`objects.obj`, and `render_sky.obj`.
|
||||
|
||||
The repository header independently authenticates the ordinary C bodies,
|
||||
operand ordering, return types, and parameter types. All three targets have
|
||||
zero relocations, so there is no unresolved owner or addend hypothesis.
|
||||
|
||||
## Candidate discipline
|
||||
|
||||
The three inline identifiers are locally macro-renamed across the include
|
||||
block, then ordinary out-of-line definitions are appended after the already
|
||||
accepted `_random_range` wrapper. Appending preserves every existing function
|
||||
section index. The macros only avoid duplicate C definitions; they do not
|
||||
change optimization, calling convention, or emitted instructions.
|
||||
|
||||
The one normal VC7 candidate compile was strict-exact on the first attempt.
|
||||
There was no object permutation, compiler-flag change, allowlist,
|
||||
adjudication, comparator exception, object patch, intrinsic, alignment
|
||||
directive, synthetic anchor, or byte-forcing expression.
|
||||
|
||||
## Exact comparison and frozen gate
|
||||
|
||||
The hardened comparator reports `all_equal: true` for the three new wrappers
|
||||
and all six previously accepted functions:
|
||||
|
||||
- `_vector_from_points2d`;
|
||||
- `_cross_product3d`;
|
||||
- `_negate_vector3d`;
|
||||
- `_random_range`;
|
||||
- `_action_obey_flush_command_indices`;
|
||||
- `_action_obey_advance_command_list`;
|
||||
- `_action_obey_begin`;
|
||||
- `_action_obey_end`;
|
||||
- `_action_obey_update`.
|
||||
|
||||
For each new wrapper, target and candidate agree on every padded byte,
|
||||
normalized hash, zero-relocation inventory, and function-section ownership.
|
||||
The frozen gate reports exactly the three wrappers as `newly_exact`, the six
|
||||
accepted siblings as `still_exact`, and `changed_nonexact: []`. Its sole
|
||||
expected structural finding is the additive symbol inventory from defining
|
||||
the wrappers.
|
||||
|
||||
## Clean committed state and replay
|
||||
|
||||
The clean committed manifest is:
|
||||
|
||||
- `build/audit/action_obey_inline_math_committed_20260826.json`;
|
||||
- commit `ef95dd016320fed49b3945c7443513b33bd005fe`;
|
||||
- SHA-256
|
||||
`c00d5c50ed2e757ddbdd96bbca96764cdc85e5a885fdc8466e96751f8a4581ed`.
|
||||
|
||||
Its pre-rebuild and post-rebuild checks return `ok: true`, no failures, no
|
||||
warnings, no changed nonexact functions, and all nine functions above as
|
||||
`still_exact`.
|
||||
|
||||
The generated object path was resolved inside this worktree. That single file
|
||||
was deleted and rebuilt once from the committed source. Raw base-object hashes
|
||||
were:
|
||||
|
||||
- before replay:
|
||||
`318e7b5cf227a3b0f6ea4258074ce0b52b10201b90bbac8835900be0020945f9`;
|
||||
- after replay:
|
||||
`fe1ece76d2544a0d01b58cdd49927a0d962c616b591441ca8c48b57393e5aa63`.
|
||||
|
||||
VC7 debug/build records are nondeterministic, so raw object hashes are not the
|
||||
equality oracle. The post-replay committed manifest is green and the direct
|
||||
hardened comparison remains `all_equal: true`.
|
||||
|
||||
Pinned artifacts:
|
||||
|
||||
- target split object:
|
||||
`0e4f889a35b97c44f6ae91e4906b547bd64f2ff12b9f399e02b46f02b69633fb`;
|
||||
- source file:
|
||||
`dbcc7c6d642babfa08ec5a1090661fc9fe35d50bb2f415700dd27d89350785dd`;
|
||||
- source blob before/after:
|
||||
`fed1a96e20b6e9e41353ef77085488e19929f948` /
|
||||
`770920ff65e3ecddff29ba1d83b12f4b189ce89a`;
|
||||
- canonical report:
|
||||
`3bab75fe187a50dd5fe76f472abe144ab33e97bca3031f67d89162f59bbd3eec`;
|
||||
- semantic report:
|
||||
`8b568709e2d795289d4c420b475f6c6e0a80646925d53145ed21703cd029ee60`;
|
||||
- VC7 compiler:
|
||||
`483e00c47bb08d699475a642bcff15b5b2036350b31c540e88a506baf101da11`;
|
||||
- hardened comparator:
|
||||
`411e41698a9491a7b69430307d03f844ee3144633e5d3038d3ffde81a8eccfb7`;
|
||||
- regression gate:
|
||||
`d09b46dd2331ff7ca677cad78a66c780c4effa41a5389f0c614c9760d7632a5f`;
|
||||
- matching methodology:
|
||||
`3eb52f6b2df7b94b4d732161c0f86e2becebbcf0b546824deb957882118b1b5c`.
|
||||
|
||||
Supporting audits:
|
||||
|
||||
- admission SHA-256:
|
||||
`f0aa45c22cc604fb74abc388b06dd79a27e7a0b498a5d28837a9e785680c9a36`;
|
||||
- parked-frontier SHA-256:
|
||||
`cfac03aea5be607c19a6a40bcdbc1164e71ffb0179602af4bd37b3fd50e26d1d`.
|
||||
|
||||
## Canonical progress and gates
|
||||
|
||||
After regeneration:
|
||||
|
||||
- canonical code: 508,669/2,198,102 bytes and 4,211/11,060 functions;
|
||||
- complete files: 377/833;
|
||||
- Halo category: 495,755/1,770,166 code bytes and 4,044/7,574 functions;
|
||||
- Halo complete files: 275/468;
|
||||
- semantic audit: 470 units and 4,319 functions evaluated, 4,176 semantic
|
||||
exact, 114 hidden-exact functions / 64,705 hidden bytes, 4,237 accepted
|
||||
exact, and zero unit errors.
|
||||
|
||||
Repository gates:
|
||||
|
||||
- object admission: zero candidates and zero revocations; only the inherited
|
||||
`shell_xbox` completion-label contradiction remains;
|
||||
- parked validation: three active, zero stale, zero invalid;
|
||||
- tooling tests: 179/179 pass;
|
||||
- Halo and libcmt dry graphs: no work;
|
||||
- protected-path touches: zero;
|
||||
- deleted tracked paths: zero;
|
||||
- no push.
|
||||
|
||||
## House-rule audit
|
||||
|
||||
Every parameter is on its own line and each wrapper ends with an explicit
|
||||
value return. The retained source is C89. It contains no assembly, `register`,
|
||||
`volatile`, barrier, pragma, explicit intrinsic, attribute, raw address,
|
||||
pointer/integer reconstruction, undefined behavior, synthetic anchor, or
|
||||
byte-forcing form. These wrappers perform no tag or object access, so the
|
||||
typed-access rules are not implicated.
|
||||
@@ -1,133 +0,0 @@
|
||||
# `action_obey.obj` Jonas public-lifecycle salvage
|
||||
|
||||
## Result
|
||||
|
||||
This bounded source-only wave starts from canonical commit
|
||||
`3f2ba63dfb1258f7e36baaec69fe495bcefdc20f`. Six ordinary public,
|
||||
one-argument stack-ABI bodies were emitted together in one natural XDK compile
|
||||
and measured independently. Five were strict in that first complete batch and
|
||||
are retained. `_action_obey_flush_structure_indices` missed and was removed
|
||||
without a second source shape or tuning pass. `action_obey.obj` advances from
|
||||
0/27 to 5/27 exact functions and from 0/11,585 to 290/11,585 meaningful code
|
||||
bytes. It remains `NonMatching` and receives no data credit.
|
||||
|
||||
| Function | Target meaningful / padded | Relocations | First candidate normalized SHA-256 | Decision |
|
||||
| --- | ---: | ---: | --- | --- |
|
||||
| `_action_obey_flush_command_indices` | `106 / 112` | 6 | `32a82f8ac1a4940e43f61ca190846d4dd6d6d2970adedde76ab0e42837ca3c03` | **retained: strict exact** |
|
||||
| `_action_obey_flush_structure_indices` | `46 / 48` | 2 | `685bb16bd7a8c09586002344b247d5aa94fe50371bf33b398b82896932470495` | rejected: target hash `9f0facf2a5e64545b5b323119ea1ce6c45813a307bf0fb256308aab64fe0db82` |
|
||||
| `_action_obey_advance_command_list` | `46 / 48` | 4 | `e1cc926aa1c23e5f6c1e9bb46b326736e53bff9e460248611ef98d43f48a8faf` | **retained: strict exact** |
|
||||
| `_action_obey_begin` | `46 / 48` | 4 | `e1cc926aa1c23e5f6c1e9bb46b326736e53bff9e460248611ef98d43f48a8faf` | **retained: strict exact** |
|
||||
| `_action_obey_end` | `46 / 48` | 4 | `e1cc926aa1c23e5f6c1e9bb46b326736e53bff9e460248611ef98d43f48a8faf` | **retained: strict exact** |
|
||||
| `_action_obey_update` | `46 / 48` | 4 | `e1cc926aa1c23e5f6c1e9bb46b326736e53bff9e460248611ef98d43f48a8faf` | **retained: strict exact** |
|
||||
|
||||
The five retained functions total 290 meaningful bytes, 304 padded bytes, and
|
||||
22 relocations. Each passes the hardened comparator in padded size, every
|
||||
normalized byte, and every relocation address, type, symbolic destination,
|
||||
and addend. Explicit terminal `return;` statements were added to satisfy the
|
||||
house source form; final validation replays prove that these style-only
|
||||
statements do not change any retained section.
|
||||
|
||||
## Provenance and one-shot boundary
|
||||
|
||||
- Baseline and restored atomic `action_obey.c` Git blob:
|
||||
`febbd96e39c7519dc21dd86a35bbe6fe7b6a4579`.
|
||||
- Retained `action_obey.c` Git blob / stable committed-payload SHA-256:
|
||||
`e0bb4361e9e4a4bf353e5cbf58037fee9b9e0169` /
|
||||
`e9160d896d224885bc51bee44329aca58cee420efb52c45875be1cee6d76e4ca`.
|
||||
The SHA is over `git cat-file blob e0bb4361...`, not checkout bytes.
|
||||
- January executable SHA-256:
|
||||
`4cc87b45f721270392a96f1674ed2b5cd4a7bb4355faeab4531d1cf1884d9520`.
|
||||
- January split `action_obey.obj` SHA-256:
|
||||
`0e4f889a35b97c44f6ae91e4906b547bd64f2ff12b9f399e02b46f02b69633fb`.
|
||||
- The preserved atomic base object is only the restored 476-byte shell,
|
||||
SHA-256
|
||||
`0c7ed4643c2075fe416eacfa9a464d49c59b8d32241755cc743e953793824454`;
|
||||
it is not a candidate oracle and preserves none of the historical bodies.
|
||||
- The supplied historical commit `677defb9d9b4dd0ac4f20bc2c5dbd53bf3e8d7f5`
|
||||
is the action-charge frontier. The independently authenticated action-obey
|
||||
atomic ledger is `f164672e22f55ade17493b2030d561d806bab2ec`, whose parent is
|
||||
`983f99f6ea9de2d43f4c17297017982ca42ac883`.
|
||||
- Clean HCEA semantic-oracle commit:
|
||||
`c168af2e747d3095d9a29418ae401f3a39544863`. The six screened body blobs are
|
||||
`7c6b1802eda90af54c7c0c81a0b3136aeac3fdff` (flush command),
|
||||
`bf1a73ee05723cd4d0fe9a63a6945f3fa1995d8b` (flush structure),
|
||||
`6599ec2fbe3b660229e331b71b789bd9d79149c8` (advance),
|
||||
`b9c9eef8510f14c386742e4405e2d7e7e52bf7ce` (begin),
|
||||
`80fb2698ca87abb6b554f6bf4a8cc0e633c838fd` (end), and
|
||||
`7ac747c1b0688fc4a38dc0a99d4ef63a84e9aaa7` (update).
|
||||
- Compiler: Microsoft 32-bit C/C++ Optimizing Compiler 13.00.9254.1 for
|
||||
80x86, SHA-256
|
||||
`483e00c47bb08d699475a642bcff15b5b2036350b31c540e88a506baf101da11`,
|
||||
with unchanged `/O2 /Oy- /DDEBUG /Dxbox` flags.
|
||||
|
||||
HCEA was used only for semantics. January's symbols, stack access,
|
||||
disassembly, literals, exact byte counts, and relocations supplied the PC
|
||||
source shape. Every selected target symbol is a COFF external function of type
|
||||
`0x20`, reads its sole `long` argument from `[ebp+8]`, and returns with the
|
||||
ordinary C stack ABI. Exactly one new exploratory six-body object was emitted.
|
||||
The rejected body was then deleted; later builds are validation replays of the
|
||||
retained source, not alternate candidate searches.
|
||||
|
||||
## Retained behavior and typed state
|
||||
|
||||
`action_obey_flush_command_indices` obtains the typed actor and its embedded
|
||||
obey state, validates the command-list index against the current scenario, and
|
||||
either marks the state finished and transitions to no action or invokes the
|
||||
private individual iterator with the command-index flush callback. The
|
||||
advance, begin, end, and update wrappers obtain the same typed state and invoke
|
||||
that iterator with their respective private callbacks.
|
||||
|
||||
The translation unit locally declares the callback function type and ordinary
|
||||
typed undefined functions. Compile-time proofs preserve the January layouts:
|
||||
simple control `0x24`, complex control `0x58`, obey state `0x84`, and the obey
|
||||
state at actor offset `0x9C`. It uses named fields and existing typed accessors.
|
||||
There is no raw address, byte-offset dereference, pointer or union pun,
|
||||
inactive-union access, volatile scheduling device, force-inline annotation,
|
||||
optimizer pragma/barrier, assembly, synthetic anchor, or object-byte forcing.
|
||||
|
||||
## Fail-closed scope, signatures, and ownership
|
||||
|
||||
The final candidate defines exactly the five retained public functions. The
|
||||
rejected `_action_obey_flush_structure_indices` definition is absent. The
|
||||
other 21 January functions are also absent, including every private
|
||||
`code_*` helper, perform/control/setup/describe, and generic inline emission.
|
||||
The six private callbacks/iterator used by the retained bodies are ordinary
|
||||
typed undefined relocations, never definitions.
|
||||
|
||||
The final object consists only of `.drectve`, `.debug$S`, and five `.text`
|
||||
COMDATs. It defines no `.rdata`, `.data`, `.bss`, COMMON symbol, or other
|
||||
storage owner; January's 1,748 data bytes remain wholly unclaimed. Only
|
||||
`source/ai/action_obey.c` and this ledger change. No header, caller,
|
||||
configuration, semantic exception, parked record, existing matching log, or
|
||||
protected source changes, and no path is deleted.
|
||||
|
||||
The current model is consumer-safe without a shared declaration. The only
|
||||
textual begin/update/end references are in the disabled action table in
|
||||
`actions.c`, while `actions.h` already models the relevant action callbacks as
|
||||
ordinary `void(long)` functions and declares no conflicting cross-TU
|
||||
signature. The private callback declarations likewise have no definitions or
|
||||
conflicting declarations elsewhere in production source.
|
||||
|
||||
## Validation
|
||||
|
||||
- Complete `halobetacache_build` and `libcmt_build`: pass (569/569 actions).
|
||||
- Direct hardened final comparison: all five retained functions remain strict;
|
||||
the rejected wrapper, the other 21 target functions, and all data owners are
|
||||
absent.
|
||||
- Semantic audit: 470 units, 4,077 functions evaluated, 3,937 semantic exact,
|
||||
101 hidden exact / 61,876 hidden code bytes, 3,998 accepted exact, and zero
|
||||
unit errors.
|
||||
- Campaign progress: 375/833 complete objects, 3,985/11,060 exact functions,
|
||||
476,985/2,198,102 meaningful code bytes, and
|
||||
1,835,088/4,176,062 matched data bytes. Halo contributes 3,818/7,574
|
||||
functions and 464,071/1,770,166 code bytes.
|
||||
- Object admission: zero candidates and zero revocations; only the inherited
|
||||
`source/shell/shell_xbox` completion-label contradiction remains.
|
||||
- Parked validation: three active, zero stale, and zero invalid entries.
|
||||
- Complete tooling suite: 179/179 tests pass.
|
||||
- `git diff --check`, deleted-path, and banned-policy scans are clean.
|
||||
|
||||
A clean committed-state regression snapshot/check followed by deletion and
|
||||
forced rebuilding of `action_obey.obj`, another regression check, and a direct
|
||||
hardened replay is the final same-path reproducibility proof. No push is
|
||||
performed.
|
||||
@@ -1,162 +0,0 @@
|
||||
# `action_obey.obj`: random-range wrapper (2026-08-26)
|
||||
|
||||
## Outcome
|
||||
|
||||
`_random_range` is newly strict-exact. The wave adds one exact function and
|
||||
27 meaningful code bytes. `action_obey.obj` now reports 6/27 exact functions
|
||||
and 317 matched meaningful code bytes. It remains incomplete; no completion
|
||||
label, semantic exception, adjudication, or data credit was added.
|
||||
|
||||
Source commit:
|
||||
|
||||
- `7bce0f67e990e5dd75e4392cbc9e6cfa4c32f6cf`
|
||||
(`Match action obey random range`)
|
||||
|
||||
## Frozen evidence and donors
|
||||
|
||||
The untouched translation unit was frozen at commit
|
||||
`3f2e6a76cb9cf575954a57e1bf3813cd312b0025` in:
|
||||
|
||||
- `build/audit/action_obey_random_range_baseline_20260826.json`;
|
||||
- manifest SHA-256
|
||||
`cc41ccbacdd5ab85bced427218def879a69dab6df5cc8f13fe9a051070f670de`.
|
||||
|
||||
January's `_random_range` is 27 meaningful / 32 padded bytes, with normalized
|
||||
SHA-256
|
||||
`7ed2e50e8e1a701a98fcceeb6a6b67e05d997f21bdb9ff5ee2e848fd1a8f409a`.
|
||||
It has exactly two `IMAGE_REL_I386_REL32` relocations:
|
||||
|
||||
- byte 12 to `_get_global_random_seed_address`;
|
||||
- byte 18 to `_seed_random_range`.
|
||||
|
||||
The repository shape atlas independently finds two exact 32-byte, two-call
|
||||
donors with identical relocation-masked instruction bytes:
|
||||
|
||||
- `source/ai/action_alert:_real_random_range`;
|
||||
- `source/camera/bored_camera:_real_local_random_range`.
|
||||
|
||||
The authenticated inline definition in `source/math/real_math.h` fixes the
|
||||
recipient's short-returning semantics and exact destinations:
|
||||
|
||||
```c
|
||||
return seed_random_range(
|
||||
get_global_random_seed_address(),
|
||||
lower_bound,
|
||||
upper_bound);
|
||||
```
|
||||
|
||||
Thus the transfer is jointly proven by January's bytes and relocations, two
|
||||
accepted ABI-shape donors, and the canonical repository source body. It is
|
||||
not a masked-byte guess.
|
||||
|
||||
## Candidate discipline
|
||||
|
||||
The header inline identifier is renamed locally across the include block, then
|
||||
the ordinary out-of-line wrapper is defined after all five previously accepted
|
||||
functions. The macro only avoids a duplicate C definition; it does not alter
|
||||
optimization, calling convention, or emitted instructions.
|
||||
|
||||
The one normal VC7 candidate compile was strict-exact. There was no
|
||||
emitted-object permutation, compiler-flag change, allowlist, adjudication,
|
||||
comparator exception, object patch, raw intrinsic call, or byte-forcing
|
||||
expression.
|
||||
|
||||
## Exact comparison and frozen gate
|
||||
|
||||
The hardened comparator reports `all_equal: true` for the new wrapper and all
|
||||
five previously accepted functions:
|
||||
|
||||
- `_random_range`;
|
||||
- `_action_obey_flush_command_indices`;
|
||||
- `_action_obey_advance_command_list`;
|
||||
- `_action_obey_begin`;
|
||||
- `_action_obey_end`;
|
||||
- `_action_obey_update`.
|
||||
|
||||
For `_random_range`, target and candidate agree on all 32 padded bytes,
|
||||
normalized hash, relocation count, both relocation addresses/types, and both
|
||||
exact destinations. The pre-commit frozen gate reports `_random_range` as
|
||||
`newly_exact`, all five accepted siblings as `still_exact`, and
|
||||
`changed_nonexact: []`. Its sole hard finding is the expected additive symbol
|
||||
inventory caused by defining the new function.
|
||||
|
||||
## Clean committed state and replay
|
||||
|
||||
The clean committed manifest is:
|
||||
|
||||
- `build/audit/action_obey_random_range_committed_20260826.json`;
|
||||
- commit `7bce0f67e990e5dd75e4392cbc9e6cfa4c32f6cf`;
|
||||
- SHA-256
|
||||
`506b7f5ff0129697a6a59056c2bf4783c36f9ccce32de4ea2346b4fa3fa60ed0`.
|
||||
|
||||
Its pre-rebuild and post-rebuild checks both return `ok: true`, no failures,
|
||||
no warnings, no changed nonexact functions, and all six functions above as
|
||||
`still_exact`.
|
||||
|
||||
The generated object path was resolved inside this worktree. That single
|
||||
generated file was deleted and rebuilt exactly once. Raw base-object hashes
|
||||
were:
|
||||
|
||||
- before replay:
|
||||
`8d320430f41df2e30729f3f419bca7c16091972b06fef62273d4b6c4bfb630c0`;
|
||||
- after replay:
|
||||
`09f54824c750107064118aabebf38a202c03c236cd83ba5e423c4816a4fffdf3`.
|
||||
|
||||
VC7 debug/build records are nondeterministic, so raw object hashes are not the
|
||||
equality oracle. The post-replay committed manifest is green and the direct
|
||||
hardened comparison remains `all_equal: true`.
|
||||
|
||||
Pinned artifacts:
|
||||
|
||||
- target split object:
|
||||
`0e4f889a35b97c44f6ae91e4906b547bd64f2ff12b9f399e02b46f02b69633fb`;
|
||||
- source file:
|
||||
`2794ea8b908210ea9bd5a94693ede143c95db1850bac1803ddb33f8269148f83`;
|
||||
- source blob before/after:
|
||||
`e0bb4361e9e4a4bf353e5cbf58037fee9b9e0169` /
|
||||
`fed1a96e20b6e9e41353ef77085488e19929f948`;
|
||||
- canonical report:
|
||||
`28e97215980d2cb6afb13e04cffda0b6ed2d893155847215138c2925250ea822`;
|
||||
- semantic report:
|
||||
`4e06bd4620272dbf7d9eebcf36e682271599afae808d7536152cc834031dbc7a`;
|
||||
- VC7 compiler:
|
||||
`483e00c47bb08d699475a642bcff15b5b2036350b31c540e88a506baf101da11`;
|
||||
- hardened comparator:
|
||||
`411e41698a9491a7b69430307d03f844ee3144633e5d3038d3ffde81a8eccfb7`;
|
||||
- regression gate:
|
||||
`d09b46dd2331ff7ca677cad78a66c780c4effa41a5389f0c614c9760d7632a5f`;
|
||||
- matching methodology:
|
||||
`3eb52f6b2df7b94b4d732161c0f86e2becebbcf0b546824deb957882118b1b5c`.
|
||||
|
||||
## Canonical progress and gates
|
||||
|
||||
After regeneration:
|
||||
|
||||
- all categories: 23.13% matched and 14.21% linked, 377/833 complete files;
|
||||
- code: 508,520/2,198,102 bytes and 4,207/11,060 functions;
|
||||
- data: 1,836,762/4,176,062 bytes;
|
||||
- Halo category: 4,040/7,574 functions;
|
||||
- semantic audit: 470 units and 4,315 functions evaluated, 4,172 semantic
|
||||
exact, 114 hidden-exact functions / 64,705 hidden bytes, 4,233 accepted exact,
|
||||
and zero unit errors.
|
||||
|
||||
Repository gates:
|
||||
|
||||
- object admission: zero candidates and zero revocations; only the inherited
|
||||
`shell_xbox` completion-label contradiction remains;
|
||||
- parked validation: three active, zero stale, zero invalid;
|
||||
- tooling tests: 179/179 pass;
|
||||
- Halo and libcmt dry graphs: no work;
|
||||
- protected-path touches: zero;
|
||||
- deleted tracked paths: zero;
|
||||
- added-source banned-construct matches: zero;
|
||||
- no push.
|
||||
|
||||
## House-rule audit
|
||||
|
||||
Each parameter is on its own line and the function ends with an explicit
|
||||
return statement. The source is C89. The retained code contains no assembly,
|
||||
`register`, `volatile`, barrier, pragma, explicit intrinsic, attribute, raw
|
||||
address, pointer/integer reconstruction, undefined behavior, synthetic anchor,
|
||||
or byte-forcing form. This wrapper performs no tag or object access, so the
|
||||
typed-access rules are not implicated.
|
||||
@@ -1,114 +0,0 @@
|
||||
# ActionObey (opus5 100K consolidated lane, waveB, 2026-09-14): describe_command and command_begin closed
|
||||
|
||||
Worker lane `opus/100k-consolidated-20260914` (worktree `C:\halo-worktrees\opus5-100k-consolidated-20260914`).
|
||||
Only `source/ai/action_obey.c` changed. Two already-written residuals became strict EXACT;
|
||||
`_action_obey_control` remains a documented register tie.
|
||||
|
||||
## 1. Scope and provenance
|
||||
|
||||
- Unit `source/ai/action_obey.c` vs January split `build/split/source/ai/action_obey.obj`.
|
||||
- Compiler VC7 13.00.9254 (XDK), repository flags for the unit (`/c /O2 /Oy- /DDEBUG /Dxbox`), unchanged.
|
||||
- Names were already authentic (January map atlas, orchestrator commit `47d9dd0da`); no rename needed.
|
||||
- Evidence: January COFF (relocations, instructions via `tools.campaign.alndiff`), Ghidra decompilation
|
||||
`C:/halo-worktrees/opus5-30k-fresh-graphs-20260914/scratch/ghidra/out/action_obey.obj.decomp.c:300-538`,
|
||||
HCEA `research-cache/halocea-full-blobs-20260830/src/blam/ai/action_obey_command_begin.c` and
|
||||
`action_obey_control.c` (semantics/order hints only).
|
||||
- Prior ledgers read: `action_obey_obj_opus5_fresh_graphs_20260914.md` (including the lead admission),
|
||||
`action_obey_obj_private_closure_plan_20260905.md`, `action_obey_obj_api_leaf_independent_review_20260905.md`,
|
||||
and the fresh-graphs worker report.
|
||||
|
||||
## 2. Validated baseline (lane HEAD)
|
||||
|
||||
`== exact 24 residual 3 unwritten 0 (of 27 listed)`, `_point_from_line3d` guard passed, no parked entries.
|
||||
|
||||
| Row | Target (padded / relocs / sha16) | Baseline candidate | First divergence |
|
||||
| --- | --- | --- | --- |
|
||||
| `_action_obey_command_begin` | 4320 / 167 / `5b56fdd8b88a4456` | 4336 / 167 | `sub esp,0x184` vs `0x174` |
|
||||
| `_action_obey_control` | 992 / equal | 992 / equal, sha differs | +0x33e register pair |
|
||||
| `_action_obey_describe_command` | 1936 / 153 / `d14c27f63086d980` | 1824 / 147 | pause arm `jmp` into a shared tail |
|
||||
|
||||
Final: `== exact 26 residual 1 unwritten 0 (of 27 listed)`, guard passed, 0 parked drift (no entries), owner
|
||||
census clean (no new code/data owner vs `build/base`; the header-inline SELECT_ANY math copies are pre-existing and
|
||||
already disclosed), `tools/fake_match_scan.py` 0 leads.
|
||||
|
||||
## 3. Accepted controls (retained in production)
|
||||
|
||||
### `_action_obey_describe_command` (now EXACT 1936/153)
|
||||
|
||||
- `relocdiff --count-by-target`: every literal/call count equal except `__snprintf` 26 vs 20, so the gap was six
|
||||
cross-jump merges, not missing code.
|
||||
- January's animate and recording NONE arms read `mov eax, offset "NONE"; push eax` after
|
||||
`mov eax, offset "<error>"`: the name is a variable, exactly like the script arm. Source now uses the
|
||||
script-arm idiom for all three tag-reference atoms: `name = "<error>"; if (index == NONE) name = "NONE";
|
||||
else if (valid) name = element; _snprintf(..., name);`. VC7 duplicates that small join (snprintf plus return)
|
||||
into both predecessors; the script join also loads a modifier table, so it is not duplicated. Ghidra shows two
|
||||
calls only because it decompiles the duplicated join.
|
||||
- HEAD's separate `_snprintf(..., "NONE")` calls pushed an immediate. That made those arms identical to other
|
||||
0x10 tails and moved VC7's cross-jump hosts across the whole function.
|
||||
|
||||
### `_action_obey_command_begin` (now EXACT 4320/167)
|
||||
|
||||
1. **Look-arm duration re-store.** January's `_ai_atom_look` valid-point arm contains
|
||||
`mov ecx,[command+4]; mov [ebp-0x28],ecx` next to the point-index store, so `look_duration = command->parameter1`
|
||||
is really stored twice. The same shape appears in look_random, which assigns the duration inside its valid arm.
|
||||
The earlier lead removed this line as a "duplicated store". The instruction is in January, and removing it
|
||||
again measures [sha].
|
||||
2. **Declaration order.** The look prologue stores point, prop, unit, then duration (-0x14, -0x30, -0x2c,
|
||||
-0x28), so `look_duration` is declared after the three NONE indices. The old order measures [sha].
|
||||
3. **Scoped prop search.** In January, `prop_iterator` (-0x1c..-0x14) and the per-player `head_position`
|
||||
(-0x20..-0x14) use overlapping storage, so their scopes are disjoint. In HEAD the prop iterator was scoped to the
|
||||
whole look_player branch, which enclosed the player loop. That pushed `data_iterator` into its own 16-byte class
|
||||
(frame +16) and split January's {direction, facing, head_position, vehicle_origin, prop_iterator,
|
||||
actor_definition} class. The prop search is now in its own block inside the look_player branch. Without it the
|
||||
size is 4336.
|
||||
4. **running_jump store order.** `delay_ticks` is written before `pause_timer`, matching the already-exact
|
||||
targeted_jump arm, which writes delay_ticks, the velocities, then pause_timer. This fixes January's EAX reload of
|
||||
`simple_control` after `test al,al`.
|
||||
|
||||
## 4. Experiment matrix
|
||||
|
||||
| Candidate | Change | Result | Kept |
|
||||
| --- | --- | --- | --- |
|
||||
| describe v1 | animate/recording as script-style if / else-if + one `_snprintf` | 1936/153 EXACT | yes |
|
||||
| begin b1 | + look-arm duration re-store | 4336, look diffs reduced | yes (step) |
|
||||
| begin b2 | + duration declared last | 4336, only frame + running_jump register | yes (step) |
|
||||
| begin b3 | + prop search block | 4320/167, frame 0x174, one EAX/ECX pick | yes (step) |
|
||||
| begin b4 | + delay_ticks before pause_timer | EXACT | yes |
|
||||
| begin n1 | b4 minus re-store | [sha] | no |
|
||||
| begin n2 | b4 with old declaration order | [sha] | no |
|
||||
| begin n3 | b4 without prop block | [size 4336!=4320] | no |
|
||||
| control c1 | alignment_vector declared before facing | identical to HEAD | no |
|
||||
| control c2 | HCEA ternary `jump_alignment_vector = normalize2d(...) == 0 ? *global_forward2d : facing;` first | worse (264 insns, register swaps spread to 0x2b7) | no |
|
||||
| control c3 | same ternary into the local, store in place | identical to HEAD | no |
|
||||
|
||||
Every whole-TU gate kept all other rows unchanged (full `--all` listing diffs).
|
||||
|
||||
## 5. Do-not-repeat
|
||||
|
||||
- describe_command: the return/break mixes from the earlier lane. The cause was the NONE-arm shape, now closed.
|
||||
- control: declaration order of facing/alignment_vector; ternary alignment forms; alignment store position;
|
||||
Ghidra single overwritten local; jump-block scope local.
|
||||
|
||||
## 6. Residual classification
|
||||
|
||||
- `_action_obey_control` (992, [sha]): ABI/register tie, measured. January gives alignment i->EDX and j->ECX
|
||||
(facing arm loads j first; join stores +0x448 before +0x444). Ours gives the inverse. Every other instruction is
|
||||
equal.
|
||||
|
||||
## 7. Reopen criteria
|
||||
|
||||
- control: a verified January idiom where an enregistered 2D vector pair is copied j-first, or new type evidence for
|
||||
`orders.move.jump_alignment_vector`.
|
||||
|
||||
## 8. Disposition
|
||||
|
||||
- `_action_obey_describe_command` and `_action_obey_command_begin`: strict EXACT, eligible for Matching
|
||||
(normalized sha16 equal to January).
|
||||
- `_action_obey_control`: still active residual, no credit.
|
||||
- Lesson: both closed rows had been labelled cross-jump/frame-packing ties. In each case the relocation count or
|
||||
slot overlap pointed to a concrete source shape. Read `relocdiff --count-by-target` and slot overlaps before
|
||||
classifying a tie.
|
||||
|
||||
## Orchestrator admission note (checkpoint 2)
|
||||
|
||||
Only `_action_obey_describe_command` was admitted (1,936 padded). The strict-exact `_action_obey_command_begin` form restores `look_duration = command->parameter1;` in the look arm, directly after the identical declaration initializer. That is a redundant store, prohibited by the house rules, and the fresh-graphs lane removed it for the same reason. Its hunks, including the bare prop-iterator block and the pause_timer/jump reorder, were reverted. The worker file is preserved as `scratch/orch/action_obey_waveB.c`. Reopen only with evidence of a non-redundant January statement shape.
|
||||
@@ -1,88 +0,0 @@
|
||||
# ActionObey (opus5 150K house-clean lane, wave w2, 2026-09-14): command_begin blocker proved, control left exhausted
|
||||
|
||||
Worker lane `opus/150k-house-clean-20260914` (base `12f7375d4`). Only `source/ai/action_obey.c` was in scope.
|
||||
**No production source changed.** `git diff --stat -- source/ai/action_obey.c` is empty, and the final real-file gate
|
||||
matches the baseline row for row.
|
||||
|
||||
## 1. Baseline (real file, whole-TU gate, `_point_from_line3d` guard passed)
|
||||
|
||||
`== exact 25 residual 2 unwritten 0 (of 27 listed)`. This unit has no `config/parked.json` entries.
|
||||
|
||||
| Row | January (padded / relocs / sha16) | Real file |
|
||||
| --- | --- | --- |
|
||||
| `_action_obey_command_begin` | 4320 / 167 / `5b56fdd8b88a4456` | 4336 / 167, frame `0x184` vs `0x174` |
|
||||
| `_action_obey_control` | 992 / equal | 992, [sha] only |
|
||||
|
||||
Inherited exact rows from earlier lanes were not touched: `_vehicle_possibility_qsort`, `_action_obey_describe_command`,
|
||||
`_action_obey_command_perform`, `_action_obey_individual_perform`, `_action_obey_perform`.
|
||||
|
||||
## 2. `_action_obey_command_begin`: NOT LANDED (policy-blocked, reopen criterion proved unsatisfiable)
|
||||
|
||||
Prior state: the 100K lane's exact file (`opus5-100k-consolidated-20260914/scratch/orch/action_obey_waveB.c`) differs from
|
||||
the real file in four hunks. The orchestrator rejected it twice because one hunk restores
|
||||
`look_duration = command->parameter1;` inside the `_ai_atom_look` valid arm, a store that repeats the declaration
|
||||
initializer. The admission note asked for a non-redundant January statement shape.
|
||||
|
||||
### January evidence (target COFF via `tools.campaign.alndiff`)
|
||||
|
||||
- Look prologue `+0x1ca..0x1e2`: `mov ecx,[ebp-4]` (command), `mov edx,[ecx+4]` (parameter1). It then stores the three
|
||||
NONE indices and `mov [ebp-0x28],edx` (duration).
|
||||
- Look valid arm `+0x205..0x213`: `mov eax,[ebp-4]; mov edi,ecx; mov ecx,[eax+4]; mov [ebp-0x14],edi; mov [ebp-0x28],ecx; jmp +0x418`.
|
||||
- Across the whole function, `[ebp-0x28]` has exactly six uses:
|
||||
- writes: `+0x1e2` (prologue), `+0x210` (look valid), `+0x2a4` and `+0x2b9` (look_random valid, `fstp`);
|
||||
- reads: `+0x418` (the join, `fld` then compare against 0.0) and `+0x4fa` (pause_timer).
|
||||
- Neither look_player nor look_object writes it. All six invalid look/look_random exits (`+0x1ee`, `+0x1ff`, `+0x229`,
|
||||
`+0x23a`, `+0x24a`, `+0x255`) jump straight to `+0x418` without a store.
|
||||
|
||||
### Dominance argument
|
||||
|
||||
The join reads the duration first on every path. On the invalid edges and on the look_player/look_object paths, the only
|
||||
reaching definition is the prologue store of `command->parameter1`. The source must therefore contain a dominating
|
||||
`look_duration = command->parameter1` (the declaration initializer or an equivalent statement). The only alternative is
|
||||
reading an uninitialized local, which is undefined behaviour and prohibited, and VC7 would not synthesize the prologue store
|
||||
in that case anyway.
|
||||
|
||||
The look-valid store copies the same value, from the same memory, into the same variable. Nothing writes `[ebp-0x28]` or
|
||||
`command->parameter1` between the two stores. Every C statement that emits these three instructions is therefore
|
||||
value-redundant.
|
||||
|
||||
HCEA (`halocea-review/src/blam/ai/action_obey_command_begin.c:261-267`, a later build) has no such store, so it offers no
|
||||
alternative January spelling. **The requested reopen criterion cannot be met on January's bytes.**
|
||||
|
||||
### Measurements (reference only, whole-TU with guard)
|
||||
|
||||
| Candidate | Change | Result |
|
||||
| --- | --- | --- |
|
||||
| `b4_waveB.c` | 100K exact form (includes the re-store) | 4320/167 EXACT; all other rows unchanged. Not landable. |
|
||||
| `n1_no_restore.c` | b4 minus only the re-store | 4320 [sha]. The three look-arm instructions are missing, and the -0x14/-0x28/-0x2c slot permutation cascades through the look_random, look_player and look_object arms. |
|
||||
|
||||
No further shapes were tried: the dominance argument covers the remaining space. Classification: policy-blocked. January
|
||||
contains a value-redundant store, so this is not a register or scheduling tie.
|
||||
|
||||
### Disposition and reopen
|
||||
|
||||
- Stays a zero-credit fuzzy genuine caller in the real file.
|
||||
- The row can close only through an explicit owner decision to admit a January-proven redundant store. The evidence for
|
||||
that decision is the 100K exact file plus the proof above. Do not requeue it for workers.
|
||||
|
||||
## 3. `_action_obey_control`: SKIPPED (exhausted, on the brief's do-not-spend list)
|
||||
|
||||
No new source or type evidence was found, so no shapes were spent.
|
||||
|
||||
Re-reading the four differing instruction pairs (`+0x33e..0x391`) gives one refinement to the 100K classification:
|
||||
|
||||
- In both builds, the pair member held in ECX is loaded first in the facing arm and stored first at the join.
|
||||
- The `global_forward2d` arm loads in memory order in both builds.
|
||||
|
||||
So the "j-first copy, +0x448 before +0x444" ordering follows from the register choice (January: i in EDX, j in ECX; ours:
|
||||
the reverse). It is not a separate statement-order fact. The residual is a pure ECX/EDX permutation of an enregistered
|
||||
`real_vector2d` (class C). HCEA `action_obey_control.c:170-180` uses the same ternary-copy semantics that were already tried.
|
||||
|
||||
Reopen criterion is unchanged from the 100K ledger: a verified January idiom that copies an enregistered 2D pair with the
|
||||
second member in ECX, or new type evidence for `orders.move.jump_alignment_vector`.
|
||||
|
||||
## 4. Final checks
|
||||
|
||||
- Final real-file gate equals the baseline (`diff` of the `--all` listings is empty); guard passed.
|
||||
- No parks for this unit, so no park drift; owner census unaffected (no edit); `tools/fake_match_scan.py` reports 0 leads.
|
||||
- Worker notes: `scratch/workers/action_obey.md`; candidates and objects: `scratch/workers/action_obey/`.
|
||||
@@ -1,178 +0,0 @@
|
||||
# ActionObey fresh-graphs lane (opus5, 2026-09-14): header-blocked private graph, measured in scratch
|
||||
|
||||
Worker lane `opus/30k-fresh-graphs-20260914` (base `c3e257e9a`, lane HEAD `47d9dd0da`).
|
||||
**No production source changed.** `git diff -- source/ai/action_obey.c` is empty; the
|
||||
final real-file gate equals the baseline. All progress below is scratch-only evidence
|
||||
for an orchestrator header packet.
|
||||
|
||||
## 1. Scope and provenance
|
||||
|
||||
- Unit `source/ai/action_obey.c` (SHA-256 `bfc668a6...5fe9`) vs January split
|
||||
`build/split/source/ai/action_obey.obj` (SHA-256 `d52f369d...600e`).
|
||||
- Compiler VC7 13.00.9254 (XDK), flags `/c /O2 /Oy- /DDEBUG /Dxbox`.
|
||||
- Names: January map atlas `scratch/atlas/action_obey.obj.txt` (all seven non-exact rows
|
||||
already carry their authentic names after orchestrator commit `47d9dd0da`).
|
||||
- Semantics: HCEA `research-cache/halocea-full-blobs-20260830/src/blam/ai/action_obey_command_{begin,perform}.c`,
|
||||
`action_obey_individual_perform.c`, `action_obey_control.c`; Ghidra
|
||||
`scratch/ghidra/out/action_obey.obj.decomp.c`; canonical uncompiled proposals
|
||||
`scratch/action_obey_command_{begin,perform}_proposal_20260905.c`; Fable donor
|
||||
`C:/halo-worktrees/fable-50k-small-families-20260904` (`f9dd42218`). No HCEA/Stian body
|
||||
exists for `action_obey_describe_command` (PC debug only).
|
||||
|
||||
## 2. Validated baseline (lane HEAD)
|
||||
|
||||
`== exact 20 residual 1 unwritten 6 (of 27 listed)`, `_point_from_line3d` guard passed,
|
||||
no parked entries for this unit.
|
||||
|
||||
| Row | Target | Status |
|
||||
| --- | ---: | --- |
|
||||
| `_action_obey_command_begin` | 4320 / 167 relocs / `5b56fdd8b88a4456` | UNWRITTEN |
|
||||
| `_action_obey_command_perform` | 1408 / 51 / `afc109dc8ddf7e3f` | UNWRITTEN |
|
||||
| `_action_obey_control` | 992 | residual [sha] |
|
||||
| `_action_obey_describe_command` | 1936 / 153 / `d14c27f63086d980` | UNWRITTEN |
|
||||
| `_action_obey_individual_perform` | 288 / 11 | UNWRITTEN |
|
||||
| `_action_obey_perform` | 192 / 8 | UNWRITTEN |
|
||||
| `_vehicle_possibility_qsort` | 64 / 0 | UNWRITTEN (no caller emits it) |
|
||||
|
||||
## 3. Results (scratch whole-TU gate, prerequisites declared scratch-only)
|
||||
|
||||
`scratch/workers/action_obey/b10.c`: `== exact 24 residual 3 unwritten 0`, all 20 baseline
|
||||
exact rows still exact, point guard passed, `tools/fake_match_scan.py` 0 leads.
|
||||
|
||||
| Row | Scratch result | Candidate text |
|
||||
| --- | --- | --- |
|
||||
| `_action_obey_perform` | **strict EXACT** | `scratch/workers/action_obey/perform.inc` |
|
||||
| `_action_obey_individual_perform` | **strict EXACT** | `BEST_individual_perform.inc` |
|
||||
| `_action_obey_command_perform` | **strict EXACT** (bytediff 0) | `BEST_command_perform.inc` |
|
||||
| `_vehicle_possibility_qsort` | **strict EXACT** (via genuine caller) | `qsort_new.inc` |
|
||||
| `_action_obey_command_begin` | 4336 / 167, frame-packing residual | `BEST_command_begin.inc` |
|
||||
| `_action_obey_describe_command` | 1824 / 147, cross-jump residual | `describe_v1.inc` (+ dialogue include) |
|
||||
| `_action_obey_control` | unchanged (register/aggregate-copy tie) | — |
|
||||
|
||||
Post-header landing file with no scratch shadows: `scratch/workers/action_obey/LANDING_after_headers.c`.
|
||||
|
||||
## 4. Why nothing landed (owner block)
|
||||
|
||||
Every new body needs declarations that belong to shared headers (brief §1 forbids worker
|
||||
header edits and TU-local shadows):
|
||||
|
||||
- `describe_command`, `command_begin`: `struct ai_{animation,script,recording}_reference_definition`
|
||||
(January element sizes 0x3c/0x28/0x28; PDB records).
|
||||
- `command_begin`/`command_perform`: go_to, look, animation_mode, crouch, grenade, vehicle,
|
||||
animate, action, targeting, initiative, wait, die modifier domains; actor fire-target and
|
||||
combat-status domains; unit animation impulses.
|
||||
- `individual_perform` requires both private bodies; `perform` requires `individual_perform`;
|
||||
the qsort comparator is emitted only through `command_begin` (static COMDAT law).
|
||||
- Owner census: the graph also emits SELECT_ANY copies of `distance_squared3d`, `dot_product2d`,
|
||||
`dot_product3d`, `vector_from_points3d`, `real_random_range`, which January references as
|
||||
undefined externals (per-caller real_math inline boundary; base already emits the
|
||||
magnitude/normalize/scale/square_root family).
|
||||
|
||||
Exact ORCHESTRATOR-PROPOSAL text, conflict lists and consumer lists:
|
||||
`scratch/workers/action_obey.md` (end of file) and `scratch/workers/action_obey/prereq.inc`.
|
||||
|
||||
## 5. Accepted source controls (evidence per shape)
|
||||
|
||||
- **command_perform**: single `done` result returned once (every January epilogue is `mov al,bl`);
|
||||
each guard path assigns its result explicitly (`else { done = TRUE; }`) — removing any one of
|
||||
the eight explicit TRUE results changes bytes (measured individually); the TRUE-atom case group is
|
||||
the last case (its `mov bl,1` block falls into the return block); `done = dot_product3d(...) >
|
||||
current_command->parameter1` for move_direction; flying/2D facing arms share one 0.984 compare via
|
||||
`goto facing_done` (HCEA CFG); assert line 983 names `current_command`; action result
|
||||
`!complex_control || !complex_control->play_action`.
|
||||
- **individual_perform**: `command_valid = FALSE; if (index < count) command_valid = TRUE;`
|
||||
(January's branchy stores; `= index < count` emits setl and swaps two byte slots).
|
||||
- **vehicle_possibility_qsort**: `<` → -1, `>` → 1, else 0 with three returns (January reloads `a`
|
||||
between compares); HEAD's `a >= b ? a > b : -1` body is the wrong shape.
|
||||
- **describe_command**: function-scope 5-entry look-modifier table, block-local tables per case
|
||||
(packed into the same top slots), 11-entry action table, 256-byte teleport buffer (frame 0x140
|
||||
exact); `dialogue_get_vocalization_name` must be prototyped (`units/dialogue_definitions.h`)
|
||||
— without it C4013 promotes the short argument with movsx.
|
||||
- **command_begin**: see §6 v10; ABI EAX=complex_control / ECX=unit_index reproduced.
|
||||
|
||||
## 6. Experiment matrix (bounded)
|
||||
|
||||
describe_command: v1 all-break 1824/147; v2 all-return identical; v3/v4 mixed return/break
|
||||
1872/149 and 1824/147; v1b + dialogue include 1824/147 (vocalize fixed). Residual = VC7
|
||||
cross-jump selection only.
|
||||
|
||||
control: single overwritten local (Ghidra form) byte-identical to HEAD; alignment store before
|
||||
targeted / first → worse; jump-block scope local → identical. Residual = reversed field order of a
|
||||
register-pair struct copy.
|
||||
|
||||
command_perform: v1 1456/52 → v2 goto facing 1424 → v3 HCEA returns 1408/51 (wrong ABI:
|
||||
complex_control register-passed) → v12 mixed 1408 regalloc right → v14 explicit guard results →
|
||||
v18 TRUE group last (1 byte) → v19b/v20 EXACT. Uninitialised-`done` probe rejected (UB, and wrong).
|
||||
|
||||
individual_perform: donor body 272; A (FALSE/if TRUE) EXACT; ternary next index 272; C 288 sha.
|
||||
|
||||
command_begin: v1 4368/179 (switch-compiled sub-dispatch) → v2 if/else chains 4320/167 →
|
||||
v3 single exit → v5 `short command_number` → v6 two distance locals → v7 double duration store
|
||||
(refs match January) → v10 scenario local / surface arg / vocalize order / biped ternary 4336/167.
|
||||
Probes inert or worse: short index local, declaration order, real_point3d facing, direction and
|
||||
iterator scope moves.
|
||||
|
||||
## 7. Do-not-repeat
|
||||
|
||||
- describe_command return/break mixes; control statement moves and local scoping; command_begin
|
||||
declaration-order permutations (density ranking ignores order off ties).
|
||||
- Never use an uninitialised result, TU-local enum/struct shadows, or non-static externs for the
|
||||
private pair.
|
||||
|
||||
## 8. Residual classification
|
||||
|
||||
- control: register/store-order tie (measured).
|
||||
- describe_command: cross-jump granularity (measured instruction-level; source cause unknown).
|
||||
- command_begin: frame-allocation packing — January classes {direction, teleport facing,
|
||||
head_position, vehicle_origin, prop_iterator, actor_definition} (end-aligned at -0x14) and
|
||||
{object_iterator, data_iterator} at -0x40; ours forms {object_iterator, facing, prop_iterator,
|
||||
actor_definition}, {direction, head, origin} and a lone data_iterator (+16 bytes). Inference, not proof.
|
||||
|
||||
## 9. Reopen criteria
|
||||
|
||||
- Header packet A–C (and census decision D) landed → gate `LANDING_after_headers.c`; land the four
|
||||
exact rows, park or keep begin/describe fuzzy.
|
||||
- command_begin: an evidence-led function-scope promotion that reproduces January's packing classes.
|
||||
- describe_command: a source-level reason for January's sparser cross-jumping.
|
||||
|
||||
## 10. Disposition
|
||||
|
||||
Still active; zero new production credit from this lane. Four rows are strict EXACT in a complete
|
||||
scratch TU pending owner-header prerequisites.
|
||||
|
||||
## Lead admission (2026-09-14): graph landed
|
||||
|
||||
The worker's scratch-only prerequisites were resolved as follows, and the
|
||||
complete private graph was then admitted:
|
||||
|
||||
- **Header prerequisite `ef7bc742a`**: `source/ai/ai_scenario_definitions.h` now
|
||||
owns the command-list atom modifier enums and the ai animation/script/recording
|
||||
reference definitions (HCEX PDB names; January element sizes 0x3C/0x28/0x28).
|
||||
`action_alert.c`'s local reference struct was removed. The full build showed
|
||||
no inherited strict loss; two already-parked fuzzy functions were re-measured
|
||||
(documented in the park evidence).
|
||||
- **TU-local enums with disclosure**: the actor fire-target and combat-status
|
||||
levels cannot be added to `actors.h` in this lane because the active
|
||||
`actor_perception.c` already defines the combat-status enumerators locally (a
|
||||
redefinition would break it). They follow canonical's existing TU-local practice
|
||||
(copies in actors.c, actor_combat.c, actor_perception.c, ai_script.c). The unit
|
||||
animation impulse enum is TU-local because units.obj is outside this lane
|
||||
(units.c declares only the count locally).
|
||||
- **Adversarial review** accepted `_action_obey_command_perform` (1,408),
|
||||
`_action_obey_individual_perform` (288), `_action_obey_perform` (192) and
|
||||
`_vehicle_possibility_qsort` (64) as strict exact, and
|
||||
`_action_obey_describe_command` (1824/147 vs 1936/153) as fuzzy. It rejected
|
||||
the first `_action_obey_command_begin` spelling for byte-inert house-rule
|
||||
defects. The lead removed the duplicated `look_duration` store, collapsed the
|
||||
extra look_player braces, re-indented the command block (whitespace only) and
|
||||
rewrote the enum provenance comments accurately. The re-gate is unchanged:
|
||||
24 exact / 3 residual / 0 unwritten, fake scan 0 leads.
|
||||
- **Disclosed owner census**: header-inline SELECT_ANY COMDAT copies
|
||||
`_distance_squared3d`, `_dot_product3d`, `_real_random_range`,
|
||||
`_vector_from_points3d` (January references them as undefined externals) and
|
||||
an unreferenced `_dot_product2d` copy. This is the same systemic class as the
|
||||
base object's pre-existing magnitude/normalize/scale/square_root copies, and
|
||||
no new non-inline code owner was added.
|
||||
- `_action_obey_command_begin` (4336/167 vs 4320/167) and
|
||||
`_action_obey_describe_command` land as zero-credit fuzzy genuine callers.
|
||||
`_action_obey_control` is unchanged.
|
||||
@@ -1,191 +0,0 @@
|
||||
# ActionObey partial callback graph reconciliation
|
||||
|
||||
Date: 2026-09-05. Parent: `c32247e7651d680dcd133d72b2fbf4e8009cc124`.
|
||||
|
||||
## Accepted result
|
||||
|
||||
The verified partial graph advances ActionObey from **10/27 to20/27 strict
|
||||
exact target functions**, **485 to2,436 meaningful code bytes**, and
|
||||
**528 to2,560 padded bytes**. New credit is **1,951 meaningful /2,032 padded
|
||||
bytes and10 functions**. Seven target functions remain unwritten; this is not
|
||||
a completed object.
|
||||
|
||||
Canonical totals after the independently checked accounting repair are
|
||||
**912,298 /2,198,102 meaningful exact code bytes**, **6,197 /11,060 credited
|
||||
functions**, **2,061,020 /4,176,062 matched data bytes**, and **391/833 Matching
|
||||
objects**. The separate stable owner sweep advances6,233 to**6,243 /8,245**,
|
||||
with zero inherited exact losses. All298 tests plus26 subtests pass.
|
||||
There are284 valid fuzzy parks, zero stale/invalid entries, and no revoked
|
||||
object admissions.
|
||||
|
||||
| New target function | Meaningful bytes | Padded bytes |
|
||||
| --- | ---: | ---: |
|
||||
| action_obey_command_end |549|560|
|
||||
| action_obey_individual_setup |110|112|
|
||||
| action_obey_individual_flush_command_indices |49|64|
|
||||
| action_obey_individual_begin |71|80|
|
||||
| action_obey_individual_advance |20|32|
|
||||
| action_obey_individual_end |72|80|
|
||||
| action_obey_individuals_iterate |290|304|
|
||||
| action_obey_command_list_setup |383|384|
|
||||
| action_obey_directmovement_update_facing |336|336|
|
||||
| action_obey_individual_update |71|80|
|
||||
|
||||
## Genuine source and private caller closure
|
||||
|
||||
Only `source/ai/action_obey.c` changes implementation. No shared header
|
||||
from the failed command-owner trial is retained. Public prototypes remain
|
||||
in the existing ACTION_OBEY owner section of `actions.h`; all nine newly
|
||||
implemented private functions are static with semantic names. The matching
|
||||
nine `config/symbols.json` records are edited in place, preserving the
|
||||
23,225-record order and every other record.
|
||||
|
||||
The public setup routine and five existing public wrappers retain the real
|
||||
iterator/callback graph. The end callback retains command_end; the update
|
||||
callback retains directmovement_update_facing. No dummy caller, emission
|
||||
anchor, forced inline, private extern ABI, or consumer-local owner declaration
|
||||
is introduced. The excluded private begin/perform pair and its individual
|
||||
perform caller are not declared as fake externs.
|
||||
|
||||
The source consumes the already accepted full swarm/obey/unit/biped records,
|
||||
typed datum/object/tag access, project boolean/real types and flag macros,
|
||||
named command cases, original assertions and PC-only loop diagnostics.
|
||||
Parameters/prototypes retain the house format and explicit returns.
|
||||
The structure-cache leaf is unchanged.
|
||||
|
||||
The real math owner supplies cross_product3d and negate_vector3d through the
|
||||
new facing caller. Their two include-time aliases and manual duplicate
|
||||
bodies are removed atomically. Both existing target bodies remain strict
|
||||
exact. Their selection metadata changes from manually emitted NODUPLICATES
|
||||
to natural header SELECT_ANY; that ownership difference is disclosed, not
|
||||
mistaken for identical object metadata. The other two inherited manual
|
||||
aliases, random_range and vector_from_points2d, are unchanged pending their
|
||||
genuine private-command callers. This partial packet does not endorse them
|
||||
as final source topology.
|
||||
|
||||
## Provenance adjudication
|
||||
|
||||
Fable's preserved donor is
|
||||
`C:/halo-worktrees/fable-50k-small-families-20260904`, commit
|
||||
`f9dd42218b3325e1b3a63d7860e5309f69fd3d8e`; it remains read-only.
|
||||
|
||||
These are authenticated reconstructions, **not a claim that all Fable bodies
|
||||
were first-shot natural matches**. Its `scratch/reports/action_obey.md`
|
||||
records an earlier early-return setup shape changed to the ordinary single
|
||||
success-result form, a command_end case ordering correction to January's
|
||||
physical case-block order, and a signed-short swarm flag correction.
|
||||
The signed field is now independently PDB-proven. The retained success-result
|
||||
control flow is meaningful, follows the engine's common single-result
|
||||
style, and matches January's state-store/dataflow. The command case order
|
||||
corresponds to the actual January layout without changing behavior or adding
|
||||
nonsensical control flow. No spelling, lifetime, declaration-order, flags,
|
||||
assembly, or source-shape search was conducted during this integration.
|
||||
This adjudication does not reopen exhausted tuning recipes elsewhere.
|
||||
|
||||
## Accounting repair, not a relaxed match
|
||||
|
||||
Ordinary objdiff reports command_end at85.26786% and the facing helper
|
||||
at96.77419%, even though complete code and ordered relocation checks pass.
|
||||
Two narrow semantic ledger entries restore their549+336 meaningful bytes:
|
||||
|
||||
- command_end:560 bytes,24 relocations, normalized SHA-256
|
||||
`f59f0185a672ce6409fe3d3c3a439e517483593f6ffc9bf5eff4b18dd4420a61`;
|
||||
- facing:336 bytes,17 relocations, normalized SHA-256
|
||||
`17b28fabb3ad4366074689d2f9be1364ccf07cdc0c7a185dbd4dff25b00e3f97`.
|
||||
|
||||
The discrepancy is compiler-local switch-label representation. Every build
|
||||
must still pass the unchanged strict comparator; no target bytes, branch
|
||||
destinations, relocation identities, or comparison policy were altered.
|
||||
Without these ledger entries the report showed911,413 bytes and6,195
|
||||
functions. The additional885 bytes are part of this same1,951-byte packet,
|
||||
not another reconstruction gain.
|
||||
|
||||
## Whole-object boundary
|
||||
|
||||
The candidate naturally emits five math functions absent from this
|
||||
ActionObey target: square_root16, scale_vector3d48, magnitude_squared3d48,
|
||||
magnitude3d48 and normalize3d96 padded bytes. All are SELECT_ANY. Only
|
||||
normalize3d has incoming candidate relocations, from the facing function at
|
||||
167 and217; the other four are header emission. The full572-base/833-target
|
||||
owner census finds byte/relocation-identical available implementations for
|
||||
each helper. **None receives ActionObey target credit.**
|
||||
|
||||
Code equality is not link compatibility. Ordinary frozen actual base/base
|
||||
links with ActionCharge fail in both input orders with LNK2005 for
|
||||
square_root, scale_vector3d, magnitude3d and normalize3d: ActionCharge owns
|
||||
NODUPLICATES copies. Both links also retain37 unrelated unresolved externals
|
||||
and produce no final binary. No FORCE, IGNORE, stub, object patch, selection
|
||||
patch, or synthetic discard pass was used. Full Ninja success means
|
||||
compilation/reporting, not successful final-image linkage.
|
||||
|
||||
An explicit ActionObey whole-object rejection records this ownership boundary
|
||||
and the remaining inherited alias topology. Target-function progress remains
|
||||
valid separately. Reopening requires authentic source/owner evidence and
|
||||
ordinary compatible canonical linkage, not manual expansion or forced
|
||||
inlining to hide helper emission.
|
||||
|
||||
## Verification evidence
|
||||
|
||||
All paths below are relative to canonical:
|
||||
`C:/Users/isabe/Documents/Codex/2026-07-13/i-w/work/rasterizer-model-wrapper-alias-20260829`.
|
||||
|
||||
- Frozen `scratch/action-obey-partial-graph-before-20260905.json` and
|
||||
`*-after-20260905.json` include source, target/base objects, symbol manifests,
|
||||
and hashes of all572 base objects. Only ActionObey changes; all571 other
|
||||
complete base-object hashes are identical.
|
||||
- Whole frozen base hashes: before
|
||||
`5335c76a7e9833303b69e3a2d3a8e71fb73ae34e2b83aac4d22642a11c6659d6`;
|
||||
after `f339f7776b58f5d044015dc363a709ac649878c918a61591a6e21a71ebedb4f9`.
|
||||
Renamed January target:
|
||||
`13a4e47de2c79a3122033539284d148cae052f5f008f084a3d15862dda844368`.
|
||||
- `scratch/action-obey-partial-graph-stable-after-20260905.json`:
|
||||
ten gains/2,032 padded bytes, zero losses.
|
||||
- Gate:20 exact, zero residual, seven unwritten; no emitted
|
||||
`_point_from_line3d`. No candidate code/data/BSS/COMMON owner is silently
|
||||
excluded from the complete-object inventory.
|
||||
- Independent object audit root replay:
|
||||
`scratch/action-obey-partial-graph-independent-object-root-20260905.json`,
|
||||
SHA-256 `321305aa1268865dfc91d598ab827ab24de37a3e9e1bfcd99880a7e3eb71c104`.
|
||||
It verifies exact positional symbol edits, all sections and all new owners.
|
||||
- Math-owner census root replay:
|
||||
`scratch/action-obey-partial-graph-math-comdat-root-20260905.json`,
|
||||
SHA-256 `6f236108159648eccef28a68c9c07e221abeedf76c268a30c093c971aaf586b6`.
|
||||
- Ordinary links:
|
||||
`scratch/action-obey-partial-graph-ordinary-links-20260905.json`,
|
||||
SHA-256 `8e0a4d74b64caae7d1867b47a1d5e50cfdf1993f260746760190eaf7eefd0ce5`.
|
||||
- Public verification tool:
|
||||
`tools/audit/action_obey_callbacks_runtime_differential.py`,
|
||||
SHA-256 `1caf0250cc996639dd792145894cfbd381fc61546c380f4d625e7b6c18833697`.
|
||||
Its target-first cases cover setup9, flush44, advance256, in target,
|
||||
actual and isolated objects. Real six-argument callback ABI, complete
|
||||
modeled0x24/0x58 state, API arguments/order, caller stack frame, ESP,
|
||||
nonvolatile registers and DF all pass. Setup's authentic null-reference
|
||||
assertion/noreturn exit is covered. Tag indices/handles stay within the
|
||||
documented valid model; this is not a whole-game execution claim.
|
||||
- `tools/test_action_obey_callbacks_runtime_differential.py` adds ten
|
||||
domain/negative-control tests. Full `tools` suite:298+26 pass.
|
||||
- Final accounted build:
|
||||
`scratch/action-obey-partial-graph-accounted-build-20260905.log`.
|
||||
Parks/admission reports have no stale park or revocation.
|
||||
- Units remains189/189 exact. Both protected bitmap source hashes are
|
||||
unchanged.
|
||||
|
||||
Reproduction of the bounded public oracle:
|
||||
|
||||
```text
|
||||
python -B tools/audit/action_obey_callbacks_runtime_differential.py --actual build/base/source/ai/action_obey.obj
|
||||
```
|
||||
|
||||
The tool requires its documented frozen target and retained HCEA donor
|
||||
evidence (or explicit paths), and refuses changed section/hash evidence.
|
||||
|
||||
## Remaining reconciliation
|
||||
|
||||
The coherent larger command-owner trial was rejected after a Units
|
||||
regression and fully restored; see
|
||||
`action_obey_obj_command_owner_trial_rejected_20260905.md`.
|
||||
Private begin/perform source proposals and corrected PDB prerequisite evidence
|
||||
remain scratch-only, uncompiled, and uncredited. Seven target functions,
|
||||
remaining data, helper ownership, and two inherited aliases still prevent
|
||||
ActionObey completion. Fable Bitmaps and other lane packets remain separate
|
||||
pending work; historical lane totals are not added to canonical.
|
||||
@@ -1,142 +0,0 @@
|
||||
# Fable `action_obey` private-closure intake (2026-09-05)
|
||||
|
||||
Read-only/source-plan audit. No production, donor, build, configuration, or generated-object file was changed or compiled. This note does not change the earlier intake accounting: the initial Fable report started at 9 exact / 0 residual / 18 unwritten, and the reported donor `+11` remains donor evidence rather than admitted campaign progress. This audit admits zero functions.
|
||||
|
||||
## Conclusion
|
||||
|
||||
The two missing routines can be restored as a coherent, genuine same-translation-unit closure:
|
||||
|
||||
```c
|
||||
static boolean action_obey_command_begin(
|
||||
long actor_index,
|
||||
long unit_index,
|
||||
short command_list_index,
|
||||
struct obey_individual_simple_control *simple_control,
|
||||
struct obey_individual_complex_control *complex_control);
|
||||
|
||||
static boolean action_obey_command_perform(
|
||||
long actor_index,
|
||||
long unit_index,
|
||||
short command_list_index,
|
||||
struct obey_individual_simple_control *simple_control,
|
||||
struct obey_individual_complex_control *complex_control);
|
||||
```
|
||||
|
||||
January proves that these are private register-ABI functions, not public ABI. `_code_000060c0` receives the complex-control pointer in EAX and unit index in ECX; actor index, command-list index, and simple-control pointer remain stack arguments. `_code_000071a0` receives unit index in EAX and its other four arguments on the stack. Those allocations are consistent with VC7 optimizing the ordinary source signature above after it sees the same-TU callers. The audit aliases should name the private sections, but production source must not declare either body non-static or manufacture an external relocation.
|
||||
|
||||
Once both bodies exist, the retained `action_obey_individual_perform` has a real private callee closure and can continue to support public `action_obey_perform`. There is no missing third private body behind either routine. The remaining preconditions are authentic shared schema and owner prototypes, not an ABI invention.
|
||||
|
||||
## Primary evidence
|
||||
|
||||
- January PC object: `build/split/source/ai/action_obey.obj`, SHA-256 `0e4f889a35b97c44f6ae91e4906b547bd64f2ff12b9f399e02b46f02b69633fb`.
|
||||
- `_code_000060c0`: 4,320 padded bytes, 167 relocations, normalized SHA-256 `5b56fdd8b88a4456f893740a2f972a21d114b032c636f6b90c9d86e0114fd640`.
|
||||
- `_code_000071a0`: 1,408 padded bytes, 51 relocations, normalized SHA-256 `afc109dc8ddf7e3f4ee6ed60f606b1e597702f063a81488fb2f8fd24f3713b07`.
|
||||
- Semantic donor, read in full:
|
||||
- `research-cache/halocea-full-blobs-20260830/src/blam/ai/action_obey_command_begin.c`, SHA-256 `4373d536adedb3dbdadfeaf62cfd1369ba2d1c53e92acae8477b6837a0a9461f`.
|
||||
- `research-cache/halocea-full-blobs-20260830/src/blam/ai/action_obey_command_perform.c`, SHA-256 `bd22ee99d261de2f8b1db20ca548bb2158031a7e0d907bdfd78a9813842bd531`.
|
||||
- `research-cache/halocea-full-blobs-20260830/src/blam/ai/action_obey_individual_perform.c`, SHA-256 `05d10cbc643b6b1b3eee5fe725bb257188a9521ea09df5deeb1370775532dade`.
|
||||
- `research-cache/halocea-full-blobs-20260830/src/blam/ai/action_obey_directmovement_update_facing.c`, SHA-256 `3295935a5a1602fe4cdbfba17bf2762734699ef1e1bc981aae5c346a6bdcb042`.
|
||||
- Retained PC source is not a full donor: Stian's `src/halo/ai/action_obey.c` is zero bytes; Punpckhdq retains the January symbol/literal manifest only; Pastudan history commit `ba72a7d7` contains only a raw-float `cross_product3d` reconstruction. It independently corroborates that math operation, but supplies neither private body.
|
||||
- Fable source reviewed: `C:/halo-worktrees/fable-50k-small-families-20260904/source/ai/action_obey.c`, SHA-256 `067b4900d5494c5341ca609337f0d220dedd4f95778a935d601427de96575a59`.
|
||||
|
||||
HCEA is an Xbox/PPC semantic donor. January PC disassembly, relocation destinations, literals, assertion strings, record strides, and register/stack use take precedence wherever the two diverge.
|
||||
|
||||
## Natural `command_begin` source plan
|
||||
|
||||
Start by resolving the typed actor, command list, current command, point block, actor definition, and actor variant. Return false if `current_command_index` is outside the command count. Dispatch on the 28 `ai_atom_type` values and use the existing simple/complex control fields:
|
||||
|
||||
1. `pause`: convert seconds to ticks (`parameter1 * 30`).
|
||||
2. `go_to` / `go_to_and_face`: validate point indices; set destination point/surface/keep-moving state; call `actor_move_to_point`; optionally call `actor_move_keep_moving_past_destination`; for the facing form, set the typed facing point.
|
||||
3. `move_direction`: sample actor body position or `object_get_origin`; for a point command call `vector_from_points3d` then `normalize3d`, otherwise use `vector3d_from_angle`; set the facing mode, halt the actor when it owns the unit, and set direct-movement flags.
|
||||
4. `look`, `look_random`, `look_player`, `look_object`: resolve a command point, active prop, nearest player, or named object; use `random_range(low, high + 1)` and `real_random_range` for the random look; construct a complete local `direction_specification` directly and call `actor_look_secondary`; store the duration in ticks. Do **not** import HCEA's one-argument/variadic `direction_get_empty` declaration: January has no such relocation and writes the local type/object/point fields directly.
|
||||
5. `animation_mode`, `crouch`, `shoot`, `grenade`: validate domains and populate complex control. Grenade setup takes the grenade type from the actor variant, calls `unit_add_grenade_type_to_inventory`, and initializes trajectory/target/timer state.
|
||||
6. `vehicle`: iterate `_object_mask_vehicle`, keep at most 16 typed `vehicle_possibility` records, compute distance, `qsort` with the already genuine same-TU `vehicle_possibility_qsort`, and try candidates through `actor_action_try_to_enter_vehicle` using the ordinary empty string literal. The record is TU-private; no public header is owed.
|
||||
7. `running_jump`, `targeted_jump`: reject the actor's mounted unit case; set jump bits/timers/velocity. January uses `dot_product3d` for the non-actor unit's facing/velocity test.
|
||||
8. `script`, `animate`, `recording`: call `hs_wake_by_name`; resolve the animation reference/default object animation graph and call `unit_start_user_animation`; update typed biped runtime flags; or resolve/play a recorded animation.
|
||||
9. `action`, `vocalize`: map modifiers to animation impulses/communication types, or fill a real `unit_speech_item`, initialize its `ai_information_packet`, and call `unit_speak`.
|
||||
10. `targeting`, `initiative`, `wait`, `loop`, `die`, `move_immediate`, `set_radius`, `teleport`: update the named flag/state fields. Teleport filters with `_object_mask_biped`, reads `biped_definition.biped.flags`, uses full 3D facing for flying/climb-anything bipeds and a typed 2D facing otherwise, then calls `object_set_position`, `object_reset`, `object_compute_node_matrices_recursive`, `actor_input_sample_position`, and `actor_move_halt`.
|
||||
|
||||
The PC-only debug epilogue must also be retained. When `ai_debug` is enabled, January formats `<no encounter>` or `encounter/squad`, calls `action_obey_describe_command(..., temporary, 256)`, and reports `"%s: %s #%d%s: %s"` with either `""` or `" FAILED"`. HCEA returns immediately after the switch and does not contain this epilogue.
|
||||
|
||||
PC-shape corrections relative to HCEA include ordinary `random_range` / `real_random_range`, `vector_from_points3d`, `distance_squared3d`, and `dot_product3d` calls; direct construction of the look-direction record; the PC debug epilogue; the January empty-string literal; and typed biped/object/tag access. HCEA's seed calls, manually expanded vector/distance products, `nullptr`, raw object header casts, and its `direction_get_empty` facade are semantic hints only.
|
||||
|
||||
## Natural `command_perform` source plan
|
||||
|
||||
Resolve the typed command and actor, default `done` to true, and use the January switch grouping:
|
||||
|
||||
- `pause` and all look atoms, plus `move_immediate`: finish when `pause_timer == 0`.
|
||||
- `go_to` / `go_to_and_face`: for the actor's own unit with complex control, test `actor_path_at_destination`; apply keep-moving tolerance/velocity logic; wait ten ticks while the actor is still moving; when destination facing is active, assert at source line 983 that the current atom is `_ai_atom_go_to_and_face`, normalize a 3D or 2D vector to the facing point, compare against `0.98400003f`, then halt on completion.
|
||||
- `move_direction`: obtain actor body position or object origin, form a vector from the stored start position, and compare its dot product with the commanded travel distance.
|
||||
- Immediate atoms (`animation_mode`, `crouch`, `vehicle`, `script`, `targeting`, `initiative`, `loop`, `die`, `set_radius`, `teleport`) return true.
|
||||
- `shoot`: require the actor unit and complex control; compare the manual fire target with the ordered point (`distance_squared3d < 0.25f`); otherwise set pause from `actor_variant_definition.ranged_combat.first_burst_delay_upper_bound * 30`, floored at 60.
|
||||
- `grenade`: inspect `unit.grenade_throw_state` after start, or call `actor_combat_plan_grenade_trajectory` and depress the trigger when the unit is not busy.
|
||||
- Jump atoms: require the jump flag, use actor `input.in_midair` or `unit_flying_through_air`, and clear the timer after the jumped bit and airborne state coincide.
|
||||
- `animate`, `recording`, `action`, `vocalize`: inspect `unit.animation.state`, `recorded_animation_controlling_unit`, `complex_control->play_action`, or `unit.speech.current.priority` respectively.
|
||||
- `wait`: preserve the January three-way combat-status/told-to-advance ladder.
|
||||
|
||||
Use `vector_from_points3d`, `distance_squared3d`, `magnitude_squared3d`, `dot_product3d`, `normalize3d`, and `normalize2d` as the typed math vocabulary instead of HCEA's manually expanded products. January's relocations authenticate every non-inlined call.
|
||||
|
||||
## Inline-math ownership and true callers
|
||||
|
||||
The four currently exact out-of-line bodies are authenticated `source/math/real_math.h` inline operations, but the present macro-renaming plus hand-appended definitions are a temporary facade. Preserve their current exact credit until the real callers are present, then remove the four include-time renames and four manual definitions atomically and let ordinary header ownership materialize them. A normal compile must prove all four sections remain exact before that cleanup is retained.
|
||||
|
||||
| Target section | January | True source caller | PC evidence |
|
||||
| --- | --- | --- | --- |
|
||||
| `_random_range` | 32 bytes, 2 relocs | `action_obey_command_begin`, `look_random` | call relocation at private-body `+0x25f`; body calls `get_global_random_seed_address` and `seed_random_range` |
|
||||
| `_vector_from_points2d` | 32 bytes, 0 relocs | `action_obey_command_perform`, non-flying destination-facing branch | the helper is inlined into `+0x211..+0x22e`: two point-coordinate subtractions followed by `normalize2d`; emitted wrapper plus inline sequence identifies the reference |
|
||||
| `_cross_product3d` | 64 bytes, 0 relocs | `action_obey_directmovement_update_facing` | two direct call relocations at `+0x9e` and `+0xd0` |
|
||||
| `_negate_vector3d` | 48 bytes, 0 relocs | `action_obey_directmovement_update_facing` | backwards/right cases are inlined at `+0x72..+0x88` and `+0x123..+0x138` |
|
||||
|
||||
For the 2D facing call, use a genuinely typed `real_point2d`/`real_vector2d` projection or authentic shared view. Do not recover it with a pointer cast between unrelated point/vector types, an inactive-union read, or a prefix facade merely to provoke the wrapper.
|
||||
|
||||
## Owner headers and API closure
|
||||
|
||||
Most dependencies already have the correct owner declarations and should be consumed by includes, not redeclared in `action_obey.c`:
|
||||
|
||||
| Owner | Required declarations/types |
|
||||
| --- | --- |
|
||||
| `source/ai/actions.h` | shared obey simple/complex/state types; `actor_action_try_to_enter_vehicle`; public ActionObey declarations |
|
||||
| `source/ai/actors.h` | `actor_datum`, `direction_specification`, movement/look/path/grenade APIs, `actor_input_sample_position` |
|
||||
| `source/ai/actor_definitions.h` | actor/variant tags, idle-look range, ranged first-burst delay, grenade properties |
|
||||
| `source/ai/ai_scenario_definitions.h` | command-list/command/point records and all atom/command-list/modifier domains |
|
||||
| `source/ai/props.h` | `prop_iterator`, `prop_iterator_new/next`, `prop_get_active_by_unit_index` |
|
||||
| `source/ai/ai_communication.h` and `source/ai/ai.h` | communication enums and complete `ai_information_packet` |
|
||||
| `source/game/players.h`, `source/memory/data.h` | `player_data`, `player_datum`, typed `data_iterator_new/next` |
|
||||
| `source/objects/objects.h`, `source/objects/object_definitions.h` | object iterators/accessors/origin/name/position/reset/node matrices, masks, damage flags, animation graph tag |
|
||||
| `source/units/units.h`, `source/units/bipeds.h`, `source/units/biped_definitions.h` | unit speech/animation/grenade/facing APIs and complete unit/biped runtime/tag fields |
|
||||
| `source/scenario/scenario.h`, `source/scenario/scenario_definitions.h` | `global_scenario_get`, command/reference blocks, encounter/squad debug names |
|
||||
| `source/cutscene/recorded_animation_definitions.h`, `source/cutscene/recorded_animations.h` | scenario animation lookup and recorded-animation control/playback |
|
||||
| `source/hs/hs.h` | `hs_wake_by_name` |
|
||||
| `source/math/real_math.h` | all point/vector/random helpers and constants |
|
||||
| `<stdlib.h>` plus project cseries/error headers | `qsort`, memset/string/format/error/debug support |
|
||||
|
||||
Two genuine owner-prototype gaps were found:
|
||||
|
||||
1. `actor_move_keep_moving_past_destination(long)` is defined by `source/ai/actor_moving.c` but is absent from `source/ai/actors.h`; `source/ai/action_charge.c` currently carries a foreign C-local declaration. Add the owner prototype to `actors.h` and remove consumer-local copies.
|
||||
2. `recorded_animation_play(long, short)` is defined by `source/cutscene/recorded_animations.c` but is absent from `source/cutscene/recorded_animations.h`; `source/hs/hs.c` currently declares it locally (with a `word` second parameter). Add the definition-compatible owner prototype to `recorded_animations.h` and remove/repair foreign copies.
|
||||
|
||||
No `direction_get_empty` declaration should be added: it is not a January dependency. `vehicle_possibility_qsort`, `action_obey_directmovement_update_facing`, `action_obey_command_begin`, and `action_obey_command_perform` remain genuine statics in this TU. `qsort` comes from the standard header, not a handwritten extern.
|
||||
|
||||
## Shared schema/enum prerequisites
|
||||
|
||||
Before integration, the owning headers must supply one authentic definition for:
|
||||
|
||||
- `obey_individual_simple_control` (0x24), `obey_individual_complex_control` (0x58), and `obey_state_data` (0x84), including direct-movement/jump union arms and every destination/action/shoot/grenade field;
|
||||
- the complete shared actor/swarm layouts already being audited separately; no obey-only prefix, opaque tail, or parallel incompatible record is acceptable;
|
||||
- `direction_specification`, `unit_speech_item`, `ai_information_packet`, `vehicle_possibility` (TU-private), and the command/reference records with January strides: command list 0x60, command 0x20, point 0x14;
|
||||
- the command-list flags, simple-control bits, atom modifier domains (look, move facing, grenade, animate, action, loop), unit animation impulses, biped runtime flags, and existing biped-definition/communication/speech/object domains in their natural owners.
|
||||
|
||||
Current Fable-local enums explicitly labeled “belongs in ...” should migrate to those owners with the full packet; they are not a reason to create another private copy. The exact signedness of the shared swarm component flags remains part of the separate schema closure and must not be inferred from this pair of functions.
|
||||
|
||||
## Admissible packet boundary
|
||||
|
||||
A coherent implementation packet is:
|
||||
|
||||
1. land the authentic shared schema and the two owner-prototype fixes;
|
||||
2. include the actual owners;
|
||||
3. add both private static bodies together, including the PC-only assertion/debug behavior and ordinary typed accesses;
|
||||
4. keep `action_obey_individual_perform` calling those statics and remove the two non-static placeholder declarations;
|
||||
5. reconcile the four math wrappers only after their true calls are present, in the same verified packet;
|
||||
6. add audit-only aliases from the two authentic names to `_code_000060c0` / `_code_000071a0` for measurement.
|
||||
|
||||
This packet is source/API/schema feasible and does not require an external facade. `command_perform` is the smaller, higher-confidence body; `command_begin` is large but semantically closed. Neither should be admitted alone if the goal is to retain public perform without unresolved private ABI.
|
||||
-455
@@ -1,455 +0,0 @@
|
||||
# ActionObey begin/perform owner prerequisites (read-only audit, 2026-09-05)
|
||||
|
||||
## Scope and disposition
|
||||
|
||||
This is the complete owner-prerequisite inventory for the frozen private
|
||||
`action_obey_command_begin` and `action_obey_command_perform` source
|
||||
proposals. The published baseline inspected was
|
||||
`c32247e7651d680dcd133d72b2fbf4e8009cc124`; concurrent root work after that
|
||||
checkpoint is outside this audit. No production source, header, build
|
||||
configuration, target metadata, gate, or object was changed here.
|
||||
|
||||
The two source proposals remain research, not admitted code:
|
||||
|
||||
- `scratch/action_obey_command_begin_proposal_20260905.c`, SHA-256
|
||||
`630ee045a17f3a095929516cd524c1ee40a385eb08d75a2b133ed99ebcca5ead`;
|
||||
- `scratch/action_obey_command_perform_proposal_20260905.c`, whose final hash
|
||||
is recorded at the end of this ledger. The earlier performer SHA-256
|
||||
`23cb0320a7b64abb4111cb3269983f50b5ff3ca7287edb455349d04a9b737ce3`
|
||||
is retained as history: it used three unauthenticated `until_...` wait
|
||||
names and incorrectly assigned an adjacent `"always"` literal to the wait
|
||||
domain. The corrected proposal uses the direct PDB names and preserves
|
||||
January's out-of-domain wait result of `TRUE`.
|
||||
|
||||
Root already exercised one coherent 86-consumer owner-header trial from the
|
||||
6,233-strict checkpoint. It lost the existing strict
|
||||
`Units::_unit_preprocess_node_orientations` owner (6,233 -> 6,232) and was
|
||||
fully restored without a name/order/source-shape retry. The frozen evidence
|
||||
is:
|
||||
|
||||
- `scratch/action-obey-command-owners-before-20260905.json`, SHA-256
|
||||
`34c077c0b3cbe43476e5e9dadc1a24fc22d29c462db23976b8ae1b8a45d8702d`;
|
||||
- `scratch/action-obey-command-owners-after-20260905.json`, SHA-256
|
||||
`090874e7e335ae137a823e4de032de6122ca89bee8860bfd397fec166a08a404`;
|
||||
- `scratch/action-obey-command-owners-restored-20260905.json`, SHA-256
|
||||
`23e6ff746d10fa75f5c23449f16903138281cac98ca62b54da20053adcd4523a`;
|
||||
- stable before/restored reports, both SHA-256
|
||||
`f714aec1804b522fbe405ea393c82a21c79569f20a19a365a43a47a77b662642`.
|
||||
|
||||
Consequently, this ledger is an actionable future boundary, not a request to
|
||||
repeat that failed trial. The begin source itself remains frozen even where
|
||||
this audit identifies better owner-constant spellings.
|
||||
|
||||
## Completeness verdict
|
||||
|
||||
The two fragments have exactly these missing shared prerequisites:
|
||||
|
||||
1. two complete actor constant domains in `source/ai/actors.h`;
|
||||
2. twelve complete command-modifier domains and three complete scenario AI
|
||||
reference records in `source/ai/ai_scenario_definitions.h`;
|
||||
3. the complete 0..13 unit-animation-impulse domain in
|
||||
`source/units/units.h`;
|
||||
4. removal of the one current scenario-record shadow in
|
||||
`source/ai/action_alert.c` and the enumerator shadows listed below; and
|
||||
5. direct inclusion of `units/unit_definitions.h` and
|
||||
`cutscene/recorded_animations.h` by `action_obey.c` when the begin body is
|
||||
integrated.
|
||||
|
||||
No additional public API is missing. The private begin/perform functions,
|
||||
`vehicle_possibility_qsort`, and
|
||||
`action_obey_directmovement_update_facing` remain same-TU `static`
|
||||
declarations. `vehicle_possibility` remains a genuine private 8-byte record;
|
||||
it is not a shared-header type. The runtime vehicle-seat-desire enum is not
|
||||
part of this packet: command validation uses the separate five-value
|
||||
`ai_atom_vehicle_modifier` domain and forwards its short value through the
|
||||
already-owned actor API.
|
||||
|
||||
## Exact actor-owner declarations
|
||||
|
||||
`source/ai/actors.h` is the genuine owner. DIA reports both domains as
|
||||
`enum <unnamed-tag>`, so use anonymous blocks and leave every datum backing
|
||||
field as `short`:
|
||||
|
||||
```c
|
||||
enum
|
||||
{
|
||||
_actor_fire_target_none = 0,
|
||||
_actor_fire_target_prop = 1,
|
||||
_actor_fire_target_manual_point = 2,
|
||||
number_of_actor_fire_targets = 3,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
_actor_combat_status_none = 0,
|
||||
_actor_combat_status_wary = 1,
|
||||
_actor_combat_status_investigate = 2,
|
||||
_actor_combat_status_definite = 3,
|
||||
_actor_combat_status_certain = 4,
|
||||
_actor_combat_status_clear_los = 5,
|
||||
_actor_combat_status_dangerous = 6,
|
||||
_actor_combat_status_visible = 7,
|
||||
NUMBER_OF_ACTOR_COMBAT_STATUS_LEVELS = 8,
|
||||
};
|
||||
```
|
||||
|
||||
Direct `HCEX_Release.pdb -sym` results authenticate every value enumerator
|
||||
and number. The lower-case `number_of_actor_fire_targets` spelling is the
|
||||
database spelling; an upper-case replacement is not authenticated. The
|
||||
terminal counts are domain/database corroboration rather than separately
|
||||
emitted PDB constants. `actor_control_data.current_fire_target_type` at
|
||||
`+0x1A0` and the actor-state combat-status fields remain `short`; declaring a
|
||||
four-byte C enum field would corrupt the authenticated layout.
|
||||
|
||||
Conflicting current declarations to remove in a coherent future packet:
|
||||
|
||||
- fire-target `none`/`prop` from the mixed blocks in
|
||||
`source/ai/actor_combat.c` and `source/ai/actors.c`;
|
||||
- the full combat-status block in `source/ai/actors.c`;
|
||||
- the partial combat-status blocks in `source/ai/actor_stimulus.c`,
|
||||
`source/ai/actor_type_infection.c`, and `source/ai/actor_type_flood.c`;
|
||||
- only `_actor_combat_status_certain` from the mixed anonymous block in
|
||||
`source/ai/ai_communication.c` (the following
|
||||
`_ai_information_none = 0` remains an explicit reset); and
|
||||
- the differently named sole alias
|
||||
`_action_charge_combat_status_clear_line_of_sight = 5` in
|
||||
`source/ai/action_charge.c`, changing its one consumer to
|
||||
`_actor_combat_status_clear_los`.
|
||||
|
||||
The complete conflict/use census and direct offset proof are preserved in
|
||||
`scratch/action_obey_actor_enum_owner_packet_20260905.md`.
|
||||
|
||||
## Exact command-modifier owner declarations
|
||||
|
||||
All of these belong in `source/ai/ai_scenario_definitions.h`. Use anonymous
|
||||
blocks: DIA exposes the source domains as anonymous enums, and command
|
||||
storage remains `short atom_modifier`.
|
||||
|
||||
```c
|
||||
enum
|
||||
{
|
||||
_ai_atom_go_to_modifier_stop_at_point = 0,
|
||||
_ai_atom_go_to_modifier_keep_moving = 1,
|
||||
NUMBER_OF_AI_ATOM_GO_TO_MODIFIERS = 2,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
_ai_atom_look_modifier_idle_aim = 0,
|
||||
_ai_atom_look_modifier_idle_turn_around = 1,
|
||||
_ai_atom_look_modifier_idle_look = 2,
|
||||
_ai_atom_look_modifier_force_facing = 3,
|
||||
_ai_atom_look_modifier_force_aim_weapon = 4,
|
||||
NUMBER_OF_AI_ATOM_LOOK_MODIFIERS = 5,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
_ai_atom_animation_mode_modifier_noncombat = 0,
|
||||
_ai_atom_animation_mode_modifier_asleep = 1,
|
||||
_ai_atom_animation_mode_modifier_combat = 2,
|
||||
_ai_atom_animation_mode_modifier_panic = 3,
|
||||
NUMBER_OF_AI_ATOM_ANIMATION_MODE_MODIFIERS = 4,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
_ai_atom_crouch_modifier_disable = 0,
|
||||
_ai_atom_crouch_modifier_enable = 1,
|
||||
NUMBER_OF_AI_ATOM_CROUCH_MODIFIERS = 2,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
_actor_atom_grenade_modifier_toss = 0,
|
||||
_actor_atom_grenade_modifier_lob = 1,
|
||||
_actor_atom_grenade_modifier_bounce = 2,
|
||||
NUMBER_OF_AI_ATOM_GRENADE_MODIFIERS = 3,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
_ai_atom_vehicle_modifier_any_non_driver = 0,
|
||||
_ai_atom_vehicle_modifier_gunner = 1,
|
||||
_ai_atom_vehicle_modifier_passenger = 2,
|
||||
_ai_atom_vehicle_modifier_driver = 3,
|
||||
_ai_atom_vehicle_modifier_any_seat = 4,
|
||||
NUMBER_OF_AI_ATOM_VEHICLE_MODIFIERS = 5,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
_ai_atom_animate_modifier_relative_movement = 0,
|
||||
_ai_atom_animate_modifier_absolute_movement = 1,
|
||||
_ai_atom_animate_modifier_absolute_movement_no_collision = 2,
|
||||
_ai_atom_animate_modifier_no_interpolation_relative_movement = 3,
|
||||
_ai_atom_animate_modifier_no_interpolation_absolute_movement = 4,
|
||||
_ai_atom_animate_modifier_no_interpolation_absolute_movement_no_collision = 5,
|
||||
NUMBER_OF_AI_ATOM_ANIMATE_MODIFIERS = 6,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
_ai_atom_action_modifier_berserk = 0,
|
||||
_ai_atom_action_modifier_surprise_front = 1,
|
||||
_ai_atom_action_modifier_surprise_back = 2,
|
||||
_ai_atom_action_modifier_evade_left = 3,
|
||||
_ai_atom_action_modifier_evade_right = 4,
|
||||
_ai_atom_action_modifier_dive_forward = 5,
|
||||
_ai_atom_action_modifier_dive_back = 6,
|
||||
_ai_atom_action_modifier_dive_left = 7,
|
||||
_ai_atom_action_modifier_dive_right = 8,
|
||||
_ai_atom_action_modifier_vehicle_woohoo = 9,
|
||||
_ai_atom_action_modifier_vehicle_scared = 10,
|
||||
NUMBER_OF_AI_ATOM_ACTION_MODIFIERS = 11,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
_ai_atom_targeting_modifier_enable = 0,
|
||||
_ai_atom_targeting_modifier_disable = 1,
|
||||
NUMBER_OF_AI_ATOM_TARGETING_MODIFIERS = 2,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
_ai_atom_initiative_modifier_enable = 0,
|
||||
_ai_atom_initiative_modifier_disable = 1,
|
||||
NUMBER_OF_AI_ATOM_INITIATIVE_MODIFIERS = 2,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
_ai_atom_wait_modifier_alerted = 0,
|
||||
_ai_atom_wait_modifier_visible_enemy = 1,
|
||||
_ai_atom_wait_modifier_told_to_advance = 2,
|
||||
NUMBER_OF_AI_ATOM_WAIT_MODIFIERS = 3,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
_ai_atom_die_modifier_normal = 0,
|
||||
_ai_atom_die_modifier_silent = 1,
|
||||
NUMBER_OF_AI_ATOM_DIE_MODIFIERS = 2,
|
||||
};
|
||||
```
|
||||
|
||||
The PDB directly authenticates the go-to values, all three wait values, and
|
||||
the exact value names used by begin for crouch enable, targeting enable,
|
||||
initiative enable, and silent death. It also authenticates look values 1..4
|
||||
and every animate/action value. The retained database headers below
|
||||
authenticate the complete look domain (including idle-aim 0), animation-mode,
|
||||
grenade, vehicle, animate, and action domains. Paired opposite values and
|
||||
terminal counts for the two-valued domains, plus the go-to/wait counts, are
|
||||
complete-domain corroboration from the retained Demon header; do not describe
|
||||
those counts as separately emitted PDB symbols.
|
||||
|
||||
There is no wait `always` member. The adjacent January `"always"` literal is
|
||||
`_ai_atom_loop_modifier_always = 0`; the already-owned loop value
|
||||
`_ai_atom_loop_modifier_until_told_to_advance = 1` remains unchanged. The
|
||||
already-admitted reconstructed move-facing block also remains unchanged and
|
||||
is not another prerequisite domain.
|
||||
|
||||
The frozen begin proposal still spells five comparisons numerically. A
|
||||
future semantic application should use the genuine names without treating
|
||||
that as a source-shape experiment:
|
||||
|
||||
- go-to `== 1` -> `_ai_atom_go_to_modifier_keep_moving`;
|
||||
- crouch `== 1` -> `_ai_atom_crouch_modifier_enable`;
|
||||
- targeting `== 0` -> `_ai_atom_targeting_modifier_enable`;
|
||||
- initiative `== 0` -> `_ai_atom_initiative_modifier_enable`;
|
||||
- die `== 1` -> `_ai_atom_die_modifier_silent`.
|
||||
|
||||
No exact-name local shadows of these twelve domains exist in canonical
|
||||
source. The present `ai_scenario_definitions.h` loop and move-facing blocks
|
||||
must not be duplicated.
|
||||
|
||||
## Exact scenario-reference records
|
||||
|
||||
These are complete tag-block element records and belong in
|
||||
`source/ai/ai_scenario_definitions.h`, adjacent to the other command-list
|
||||
schema. Direct `HCEX_Release.pdb -type` output authenticates every field
|
||||
name, field type, offset, and total size; none of the fields below is a
|
||||
speculative tail name.
|
||||
|
||||
```c
|
||||
struct ai_animation_reference_definition
|
||||
{
|
||||
char animation_name[TAG_STRING_LENGTH + 1];
|
||||
struct tag_reference animation_graph;
|
||||
unsigned long unused[3];
|
||||
};
|
||||
|
||||
struct ai_script_reference_definition
|
||||
{
|
||||
char script_name[TAG_STRING_LENGTH + 1];
|
||||
unsigned long unused[2];
|
||||
};
|
||||
|
||||
struct ai_recording_reference_definition
|
||||
{
|
||||
char recording_name[TAG_STRING_LENGTH + 1];
|
||||
unsigned long unused[2];
|
||||
};
|
||||
|
||||
typedef char ai_animation_reference_definition_size_assert[
|
||||
sizeof(struct ai_animation_reference_definition) == 0x3C ? 1 : -1];
|
||||
typedef char ai_script_reference_definition_size_assert[
|
||||
sizeof(struct ai_script_reference_definition) == 0x28 ? 1 : -1];
|
||||
typedef char ai_recording_reference_definition_size_assert[
|
||||
sizeof(struct ai_recording_reference_definition) == 0x28 ? 1 : -1];
|
||||
```
|
||||
|
||||
The exact offsets are animation name `+0`, tag reference `+0x20`, unused
|
||||
dwords `+0x30`; script/recording name `+0`, unused dwords `+0x20`.
|
||||
|
||||
The only current declaration conflict is the complete local
|
||||
`struct ai_animation_reference_definition` at
|
||||
`source/ai/action_alert.c:76`. It must be removed so that the already-present
|
||||
`#include "ai_scenario_definitions.h"` supplies the owner. Its local
|
||||
`long unused[3]` has the right width but the PDB owner type is
|
||||
`unsigned long`. There is no current script- or recording-reference shadow.
|
||||
The `scenario` structure's corresponding members remain `struct tag_block`;
|
||||
no scenario prefix or retyping is required.
|
||||
|
||||
## Exact unit-animation-impulse owner declaration
|
||||
|
||||
`source/units/units.h` is the genuine public constant owner. Again use an
|
||||
anonymous enum and keep the existing public function parameters as `long`
|
||||
and the private mapper's parameters as `short`:
|
||||
|
||||
```c
|
||||
enum
|
||||
{
|
||||
_unit_animation_impulse_berserk = 0,
|
||||
_unit_animation_impulse_signal_move = 1,
|
||||
_unit_animation_impulse_signal_attack = 2,
|
||||
_unit_animation_impulse_signal_warn = 3,
|
||||
_unit_animation_impulse_surprise_front = 4,
|
||||
_unit_animation_impulse_surprise_back = 5,
|
||||
_unit_animation_impulse_evade_left = 6,
|
||||
_unit_animation_impulse_evade_right = 7,
|
||||
_unit_animation_impulse_dive_front = 8,
|
||||
_unit_animation_impulse_dive_back = 9,
|
||||
_unit_animation_impulse_dive_left = 10,
|
||||
_unit_animation_impulse_dive_right = 11,
|
||||
_unit_animation_impulse_vehicle_celebrate = 12,
|
||||
_unit_animation_impulse_vehicle_panic = 13,
|
||||
NUMBER_OF_UNIT_ANIMATION_IMPULSES = 14,
|
||||
};
|
||||
```
|
||||
|
||||
Direct `HCEX_Release.pdb -sym` queries return every value enumerator with
|
||||
exactly these names and values. The terminal count 14 is supported by the
|
||||
complete January range/switch and database domain, not a separately emitted
|
||||
PDB constant. The immutable HCEA header's older `GUESS` prose predates this
|
||||
direct PDB check and does not downgrade the now-authenticated value names.
|
||||
|
||||
Current canonical has no local value-name shadow. Remove only
|
||||
`NUMBER_OF_UNIT_ANIMATION_IMPULSES = 14` from the mixed block near
|
||||
`source/units/units.c:708`; retain `_unit_seat_unknown8_bit = 8`.
|
||||
For a complete semantic migration, replace the raw 0..13 cases in both
|
||||
switches of private `code_00198e40` and the raw 12..13 range tests in private
|
||||
`code_00198fd0` with these owner constants. The PDB authenticates
|
||||
`code_00198e40` as
|
||||
`static short unit_animation_impulse_get_index(short, short *)`; that private
|
||||
symbol rename is useful metadata cleanup but is not an API prerequisite and
|
||||
must not be put in a header.
|
||||
|
||||
## Prototype and include boundary
|
||||
|
||||
The corrected performer needs no prototype or type beyond the four owner
|
||||
domains it names: go-to, wait, fire-target, and combat-status. Its callees
|
||||
are already declared by their genuine headers.
|
||||
|
||||
The begin proposal needs no additional shared type/prototype beyond the
|
||||
modifier domains, unit impulse, and three reference records above. Two
|
||||
direct-owner includes are required when it is placed into the real TU:
|
||||
|
||||
- `#include "units/unit_definitions.h"` for the
|
||||
`unit_definition_get(index)` owner macro and complete
|
||||
`struct unit_definition` dereference;
|
||||
- `#include "cutscene/recorded_animations.h"` for
|
||||
`boolean recorded_animation_play(long unit_index, short animation_index)`.
|
||||
|
||||
Preserve the existing direct `#include "math/real_math.h"`; it owns the
|
||||
normalization/vector APIs, including the accepted 3D-prefix-as-2D convention.
|
||||
`actor_move_keep_moving_past_destination(long)` is already correctly owned by
|
||||
`actors.h` and matches the definition in `actor_moving.c`. Do not add any
|
||||
caller-local extern declarations.
|
||||
|
||||
All other required owners are already present: `actions.h`, `actors.h`,
|
||||
`actor_definitions.h`, `ai_communication.h`, `props.h`, `objects.h`,
|
||||
`scenario.h`, `units.h`, `bipeds.h`, `hs.h`, and the recorded-animation,
|
||||
object-definition, player, data, and C runtime owners selected in the natural
|
||||
candidate skeleton.
|
||||
|
||||
## Evidence and provenance
|
||||
|
||||
Authoritative local artifacts:
|
||||
|
||||
- PDB:
|
||||
`../../research/hcea_jun2011_prototype/payload/Halo CE Anniversary (Jun 24 2011)/HCEX_Release.pdb`,
|
||||
SHA-256
|
||||
`0fd11b084fd2169cafe071fd8c3e4083d6e9564f01e7964f6c26e5a03eee4dff`;
|
||||
- secondary PDB:
|
||||
`../../research/hcea_jun2011_prototype/payload/Halo CE Anniversary (Jun 24 2011)/HCEX.pdb`,
|
||||
SHA-256
|
||||
`f55cfe957da8079a62a26a6753f1ddbb700b067a66de0bd5db5aac182d985ff1`;
|
||||
- DIA reader: `../../research/tools/DIA2Dump/x64/Release/DIA2Dump.exe`,
|
||||
SHA-256
|
||||
`5be3b890fb5c3b7c74b7c3ce7c275a70f48813c388d3611c41e69c0ac0626243`;
|
||||
- January `action_obey.obj`: current split artifact SHA-256
|
||||
`13a4e47de2c79a3122033539284d148cae052f5f008f084a3d15862dda844368`;
|
||||
the earlier frozen source-body audit recorded SHA-256
|
||||
`0e4f889a35b97c44f6ae91e4906b547bd64f2ff12b9f399e02b46f02b69633fb`
|
||||
before later semantic target-metadata regeneration;
|
||||
- retained full-domain header:
|
||||
`../../research/players_update_cluster_research/upstream/demon/source/ai/ai_scenario_definitions.h`,
|
||||
SHA-256
|
||||
`d650fce71f3f8f1cc9e1c5e02b350bb56b65b8de385ef1a7d93257410de2106c`.
|
||||
|
||||
Immutable HCEA database extracts, used as corroborative reconstructions rather
|
||||
than original source:
|
||||
|
||||
```text
|
||||
33fb4dd6bdc543a755d068186d18f472e679bcfd12835ffa020866dbef33db27 ai_atom_animation_mode_modifier.h
|
||||
b9cf105849bd637b2c1b7011578ddb204f67e35ac5dce696eb6217a12323e412 actor_atom_grenade_modifier.h
|
||||
586f4f8473f15d34370598a74ae3637a4d377ca37b938398de892ca0633deed8 ai_atom_vehicle_modifier.h
|
||||
66b289cef8e9af8e497f552bdbf2a149b0396d6814800f0db1d7d82f73aa0570 ai_atom_look_modifier.h
|
||||
df5ed09edc01002f3568b353cdf5ae24784a294b8ddcc92d9b6ccf3c9171851c ai_atom_animate_modifier.h
|
||||
1919399bdc4cf367a73e1e71d7c17abdf5a2c5b481b40b97ea6e020362c832fc ai_atom_action_modifier.h
|
||||
6d367a2adacf78a8c89b7e8a2cc566572e5fd0419fe92fd979affcd5abe74020 unit_animation_impulse.h
|
||||
c34d83224cf95b071a9de847bdd1a98e63bde836ae6d622beb3351a990b2da72 ai_animation_reference_definition.h
|
||||
16f251ee304111c333f39f2a495da1b65dcd91d154a151592a8f2f81ac63330f ai_script_reference_definition.h
|
||||
b96e456964ea532b65afac96fbf4360f8cee954d51beb0ab374127a0ced4f68d ai_recording_reference_definition.h
|
||||
```
|
||||
|
||||
All ten files are under
|
||||
`../../research-cache/halocea-full-blobs-20260830/src/headers/`.
|
||||
|
||||
Final supporting scratch revisions:
|
||||
|
||||
```text
|
||||
630ee045a17f3a095929516cd524c1ee40a385eb08d75a2b133ed99ebcca5ead action_obey_command_begin_proposal_20260905.c
|
||||
1a9392214a2ca5be3eb0f214d38cc0c67f3d18ddabaa339df27165c7726c774b action_obey_command_perform_proposal_20260905.c
|
||||
46e78d3c070638fab00d3f0c5334088b91146f92224330a5964ee4b358d8cd57 action_obey_actor_enum_owner_packet_20260905.md
|
||||
1e554e3d6f43775d645302ffb4d0eb297e7e65d51983a938b006282f836a23af action_obey_command_begin_proposal_issues_20260905.md
|
||||
```
|
||||
|
||||
## Provenance limits and final boundary
|
||||
|
||||
- Enum tag names are not PDB-authenticated; use anonymous enums.
|
||||
- PDB proves the value enumerators described above. Terminal counts and the
|
||||
non-emitted counterparts in two-valued domains are domain-completion
|
||||
evidence from the retained source/database and January range behavior.
|
||||
- The three scenario-reference records are stronger: every field name/type,
|
||||
offset, and size is direct PDB evidence. No field is a speculative facade.
|
||||
- HCEA `src/blam` bodies and extracted headers are binary reconstructions, not
|
||||
recovered first-party source.
|
||||
- The frozen begin's numeric boolean comparisons are known owner-name debt,
|
||||
not an invitation to edit or compile another variant now.
|
||||
- The failed 86-consumer owner trial is the current integration blocker.
|
||||
Reopen only with a genuinely changed shared-header/consumer context, not
|
||||
spelling, enum-tag, declaration-order, include-order, or compiler-steering
|
||||
experiments.
|
||||
-163
@@ -1,163 +0,0 @@
|
||||
# ActionObey: shared owners and structure-cache flush reconciliation
|
||||
|
||||
Date: 2026-09-05. Parent publication: `31a1927c951479106d0475ee99e1fb236a15e89d`.
|
||||
|
||||
## Accepted checkpoint and accounting
|
||||
|
||||
This checkpoint adds the genuine `action_obey_flush_structure_indices` leaf
|
||||
and repairs the shared types, enum owners, and public API declarations needed
|
||||
by the larger Fable ActionObey packet. It does not import that packet wholesale.
|
||||
|
||||
- ActionObey advances from 9/27 to **10/27 exact functions**, 439 to **485
|
||||
meaningful code bytes**, and 480 to 528 padded bytes.
|
||||
- Incremental credit is **46 meaningful / 48 padded bytes**, one function,
|
||||
and no data. The complete-object count does not change.
|
||||
- The final canonical build reports **910,347 / 2,198,102 meaningful exact
|
||||
code bytes**, **6,187 / 11,060 credited functions**, **2,061,020 / 4,176,062
|
||||
matched data bytes**, and **391/833 Matching objects**.
|
||||
- The complete stable sweep advances 6,232 to **6,233** exact owners out of
|
||||
8,245 measured owners, with zero inherited exact losses. This owner census
|
||||
is not the same denominator or admission policy as the credited-function total.
|
||||
|
||||
Canonical root:
|
||||
`C:/Users/isabe/Documents/Codex/2026-07-13/i-w/work/rasterizer-model-wrapper-alias-20260829`.
|
||||
Donor root, read-only throughout:
|
||||
`C:/halo-worktrees/fable-50k-small-families-20260904`, tip
|
||||
`f9dd42218b3325e1b3a63d7860e5309f69fd3d8e`.
|
||||
|
||||
## Source ownership and credibility
|
||||
|
||||
`actions.h` owns the public ActionObey declarations. The packet adds the nine
|
||||
genuine target-public declarations in its existing ACTION_OBEY section and
|
||||
removes their six consumer-local copies from `actions.c`. The redundant
|
||||
`actor_action_change` declaration in `action_obey.c` is removed; its existing
|
||||
owner declaration is unchanged.
|
||||
|
||||
The leaf uses `actor_get`, the complete `obey_state_data`, the named
|
||||
`destination_valid` and `destination_surface_index` fields, `NONE`, and an
|
||||
explicit return. January independently materializes the obey state at actor
|
||||
offset 0x9C, tests the byte at 0xCC, and conditionally stores -1 at 0xDC.
|
||||
|
||||
Provenance adjudication: this is an authenticated exact reconstruction, **not
|
||||
a natural first-shot result**. Fable's report says the local `state_data`
|
||||
pointer corrected an earlier missed candidate. That history remains visible
|
||||
in the independent review. The accepted pointer is ordinary meaningful source,
|
||||
matches adjacent action-family source organization, and is independently
|
||||
supported by the target state-base computation. It is not an inert lifetime
|
||||
anchor, aliasing trick, or invented control flow. This ruling does not authorize
|
||||
replaying exhausted spelling/order searches on other functions.
|
||||
|
||||
The shared owner correction is one coherent packet:
|
||||
|
||||
- `actors.h` owns the full 0x40 `swarm_component_datum`, the 0x14
|
||||
`swarm_wander_control`, the five component flags, and `swarm_component_get`.
|
||||
Direct HCEX and HCEX_Release PDB records prove signed `short flags`, the
|
||||
explicit byte `pad` at 0x1B, and the complete anonymous wander/obey union at
|
||||
0x1C. The wander record has ordinary implicit alignment, not an invented
|
||||
named padding field. Local partial/duplicate views are removed from
|
||||
`actors.c`, `actor_type_infection.c`, and `actor_perception.c`.
|
||||
- `actions.h` owns the five simple-control bits. Existing 0x24/0x58/0x84
|
||||
obey record shapes are unchanged. Infection's local copies are removed.
|
||||
- `bipeds.h` owns the six directly authenticated runtime bits. Bit zero is
|
||||
airborne, not limping. The five misleading uses in `units.c` and one in
|
||||
`players.c` are renamed; duplicate local enums in Infection, Bipeds, and
|
||||
PlayerControl are removed. All values and underlying datum storage remain
|
||||
unchanged. Units remains **189/189 exact**.
|
||||
- `ai_scenario_definitions.h` owns the five authenticated command-list bits,
|
||||
loop-until modifier, and four movement-facing values. The latter names are
|
||||
explicitly descriptive reconstructions from January behavior, not claimed
|
||||
recovered spellings. Unneeded later manual-BSP and count names are not imported.
|
||||
- `actors.h` owns `actor_move_keep_moving_past_destination(long)` and
|
||||
`action_charge.c` loses its foreign local declaration.
|
||||
- `recorded_animations.h` owns the genuine play/play-and-delete/play-and-hover
|
||||
signatures `(long, short)`. `hs.c` includes that owner and loses the three
|
||||
mismatched local `(long, word)` declarations. Definition and caller code
|
||||
are unchanged.
|
||||
|
||||
No private begin/perform facade, flat obey-only swarm view, new raw offset,
|
||||
new inline directive, or new math wrapper is introduced by this checkpoint.
|
||||
It does not bless the inherited ActionObey math-wrapper/callback debt: that
|
||||
requires the real private caller graph and remains the next reconciliation step.
|
||||
|
||||
## Verification and the two residual changes
|
||||
|
||||
The public-header phase freezes all 47 actual Ninja consumers: 3,079 runtime
|
||||
sections unchanged, 54 compiler-local-label spelling changes, and no runtime,
|
||||
owner, COMMON, or forbidden point-helper addition. All 6,232 exact owners survive.
|
||||
|
||||
The subsequent shared-schema phase freezes all **58 actual consumers**, not
|
||||
merely lexical include matches. Its full runtime comparison has 4,544 unchanged
|
||||
sections, 62 compiler-local-label-only changes, and exactly two residual code
|
||||
changes. Neither was accepted from strict-function counts alone:
|
||||
|
||||
1. `infection_swarm_control` remains 3,360 padded bytes with 103 relocations.
|
||||
Three clear-bit masks use shorter signed-immediate encodings after the
|
||||
authenticated signed-word field correction. Exhaustive evaluation covers
|
||||
every 16-bit flag value at all three sites: **196,608 comparisons pass**.
|
||||
The first two sites explicitly zero upper EAX. The third does not require
|
||||
that assumption: only AL is tested and AX stored; TEST replaces the flags,
|
||||
and both successor paths fully define EAX before reading it full-width.
|
||||
All 130 direct branches, both table jumps, all 103 relocation records,
|
||||
shifted local labels, exact allowed alignment bytes, and the masked
|
||||
80-byte table/tail are checked. No owner, data, COMMON, or definition changes.
|
||||
2. `ai_communication_update_speech_timers` remains 672 bytes with the same 43
|
||||
ordered relocations. Its only change swaps the independent loads of DI
|
||||
from `[EBP+0x10]` and EBX from `[EBP-8]` in 0x167..0x16E. All 27 branches
|
||||
are unchanged; none enters the block interior; there is no indirect jump
|
||||
or relocated operand in the block. The rest of the bytes are identical.
|
||||
Its honest fuzzy score returns from 97.76382% to the previously observed
|
||||
**97.67839%**. This is explicitly disclosed, not hidden as an exact gain.
|
||||
No speech-timer source or scheduling hint was changed.
|
||||
|
||||
The first Ninja invocation compiled the consumers but correctly stopped its
|
||||
progress step on the now-stale speech-timer evidence. Only after full semantic
|
||||
review and independent proof was that park remeasured. Final Ninja succeeds.
|
||||
Root independently replays the hardened residual proof with the same JSON hash.
|
||||
The final 58-object freeze matches the reviewed after-freeze across all **4,608
|
||||
runtime sections** with no changes at all.
|
||||
|
||||
Final checks:
|
||||
|
||||
- Complete stable sweep: +1 exact function / 48 padded bytes, zero losses.
|
||||
- Leaf: **1,024 cases each** against the January target, final actual object,
|
||||
and isolated build. All 256 flag-byte representations and four surface
|
||||
values; full modeled actor-state writes, call arguments, stack, preserved
|
||||
registers, and direction flag checked. Limit: valid modeled actor handle
|
||||
and `datum_get` contract, not a whole-game execution test.
|
||||
- Separate VC7 scratch TU: **24 compile-time layout/value checks** pass;
|
||||
it emits no code and earns no progress credit.
|
||||
- **288 tests plus 26 subtests pass** after the final park update.
|
||||
- Parks: **284 active, zero stale, zero invalid**.
|
||||
- Admission: zero candidates, zero contradictions, five existing displayed
|
||||
rejections, zero revocations. No new `_point_from_line3d` emission/reference.
|
||||
- Protected bitmap source/header hashes are unchanged. No source implementation
|
||||
in the new Opus rasterizer/device/widget reservation is modified.
|
||||
|
||||
## Frozen evidence and continuation
|
||||
|
||||
Key manifests (all under canonical `scratch/`):
|
||||
|
||||
- `action-obey-public-api-before-20260905.json` / `...after...`:
|
||||
`22082d37d81366a681520949d9502107f7ea43b8e185f29936643cd07c89d0d5`
|
||||
/ `49d6f456321f119a67d25ac7324d82b4fc282d43cf1e86044f4a342e43284f65`.
|
||||
- `action-obey-shared-schema-before-20260905.json` / `...after...` / `...final...`:
|
||||
`90becfaff10da7f9e549e43d28385da41c37675d51d3c9319347bb7b71600253`
|
||||
/ `b7fef54d4e8030efd58299c5dd290f7e3e9a0ba0c80e8bd8aaa70a929d95c831`
|
||||
/ `d88762b5f013727b37c746f8e290a5719779e40ec00a9ae10b5accc6e9fd24bb`.
|
||||
- `action_obey_shared_schema_residual_independent_proof_v2_20260905.json`
|
||||
and root replay both hash
|
||||
`2a673deafe4714f0ad74ff074feb24d8cb34cb4f87fe6485fbca89d5911c2e4f`.
|
||||
- `action-obey-structure-leaf-final-runtime-20260905.json`:
|
||||
`b4ce9623dafa0c31d541f6a6aa16528c3c843522f542c47e367c45566b08e059`.
|
||||
|
||||
See the sibling API/leaf independent review, shared-schema evidence, and
|
||||
shared-schema residual proof ledgers for source hashes and detailed ownership.
|
||||
The private-closure plan is preserved separately. Both real private command
|
||||
bodies, further actor/modifier enum ownership, and ordinary math-header
|
||||
materialization remain scratch research until their coherent packet passes.
|
||||
Do not count the donor's remaining exact claims or these proposals as integrated.
|
||||
|
||||
The separate Bitmaps intake preserves 18 distinct donor exact candidates /
|
||||
4,736 padded bytes, with prototype/ownership/provenance issues still awaiting
|
||||
reconciliation. It adds no canonical credit in this checkpoint. The Fable lane
|
||||
as a whole remains unfinished; donor committed and dirty work is preserved.
|
||||
@@ -1,340 +0,0 @@
|
||||
# ActionObey shared swarm schema and enum-owner audit (2026-09-05)
|
||||
|
||||
## Disposition
|
||||
|
||||
The shared `swarm_component_datum` / `swarm_wander_control` schema is
|
||||
authenticated strongly enough for one coherent owner-header trial. The
|
||||
natural owner is `source/ai/actors.h`: that header already owns
|
||||
`swarm_datum`, `SWARM_COMPONENT_DATUM_SIZE`, `swarm_data`,
|
||||
`swarm_component_data`, and the neighboring actor/swarm accessors.
|
||||
|
||||
The decisive evidence is direct DIA type information in both `HCEX.pdb` and
|
||||
`HCEX_Release.pdb`, not the Fable donor's flat local view. In particular,
|
||||
`swarm_component_datum.flags` is a signed `short`, the byte at `+0x1B` is an
|
||||
explicit member named `pad`, and the `+0x1C` tail is an anonymous union of
|
||||
`wander` and `obey`. `swarm_wander_control` has no named member at `+2`;
|
||||
that two-byte interval is ordinary alignment before its vector.
|
||||
|
||||
This is a read-only/source-ownership result. No production, donor, header,
|
||||
configuration, build, or object file was changed or compiled by this audit.
|
||||
The current root-owned ActionObey API/flush-leaf work was observed but not
|
||||
modified or re-audited here.
|
||||
|
||||
## Direct PDB schema
|
||||
|
||||
Reproduction tool:
|
||||
|
||||
`C:/Users/isabe/Documents/Codex/2026-07-13/i-w/research/tools/DIA2Dump/x64/Release/DIA2Dump.exe`
|
||||
|
||||
Primary type source:
|
||||
|
||||
`C:/Users/isabe/Documents/Codex/2026-07-13/i-w/research/hcea_jun2011_prototype/payload/Halo CE Anniversary (Jun 24 2011)/HCEX.pdb`
|
||||
|
||||
SHA-256: `f55cfe957da8079a62a26a6753f1ddbb700b067a66de0bd5db5aac182d985ff1`
|
||||
|
||||
Independent same-result PDB:
|
||||
|
||||
`C:/Users/isabe/Documents/Codex/2026-07-13/i-w/research/hcea_jun2011_prototype/payload/Halo CE Anniversary (Jun 24 2011)/HCEX_Release.pdb`
|
||||
|
||||
SHA-256: `0fd11b084fd2169cafe071fd8c3e4083d6e9564f01e7964f6c26e5a03eee4dff`
|
||||
|
||||
The relevant commands are `DIA2Dump.exe -sym <name> <pdb>`. Both PDBs give
|
||||
the same two principal layouts:
|
||||
|
||||
| type/member | offset | DIA type |
|
||||
| --- | ---: | --- |
|
||||
| `swarm_component_datum` | | size `0x40` |
|
||||
| `identifier` | `0x00` | `short` |
|
||||
| `flags` | `0x02` | `short` |
|
||||
| `position` | `0x04` | `real_point3d` |
|
||||
| `surface_index` | `0x10` | `long` |
|
||||
| `combat_target_prop_index` | `0x14` | `long` |
|
||||
| `attached_to_unit_ticks` | `0x18` | `unsigned char` |
|
||||
| `ground_ticks` | `0x19` | `unsigned char` |
|
||||
| `attack_delay_ticks` | `0x1A` | `unsigned char` |
|
||||
| `pad` | `0x1B` | `unsigned char` |
|
||||
| `wander` | `0x1C` | `struct swarm_wander_control` |
|
||||
| `obey` | `0x1C` | `struct obey_individual_simple_control` |
|
||||
| `swarm_wander_control` | | size `0x14` |
|
||||
| `pause_ticks` | `0x00` | `unsigned char` |
|
||||
| `move_ticks` | `0x01` | `unsigned char` |
|
||||
| implicit alignment | `0x02..0x03` | no DIA member |
|
||||
| `vector` | `0x04` | `real_vector3d` |
|
||||
| `angle` | `0x10` | `float` |
|
||||
|
||||
The already-shared ActionObey arm in `actions.h` also agrees with the PDB:
|
||||
`obey_individual_simple_control` is `0x24`, with bytes at `+0/+1`, signed
|
||||
`short pause_timer` at `+2`, bytes at `+4/+5`, and anonymous
|
||||
`directmovement` / `jump` arms at `+8`. The direct-movement arm is `0x1C`
|
||||
(`short facing +0`, vector `+4`, start position `+0x10`); the jump arm is
|
||||
`0x0C` (`short delay_ticks +0`, reals `+4/+8`). Those existing records need
|
||||
no shape change.
|
||||
|
||||
`DIA2Dump -sym swarm_component_data HCEX.pdb` identifies the global as
|
||||
`struct data_array *`, matching the existing `actors.h` declaration.
|
||||
|
||||
## Source-authentic owner shape
|
||||
|
||||
The following is the evidence-backed shape for `actors.h`. The enumerator
|
||||
count is deliberately omitted because the named `NUMBER_OF_*` symbol is not
|
||||
present in either PDB and no current consumer needs it.
|
||||
|
||||
```c
|
||||
enum
|
||||
{
|
||||
_swarm_component_attacking_in_melee_bit = 0,
|
||||
_swarm_component_attached_to_unit_bit,
|
||||
_swarm_component_wander_bit,
|
||||
_swarm_component_obey_bit,
|
||||
_swarm_component_obey_desire_jump_bit,
|
||||
};
|
||||
|
||||
struct swarm_wander_control
|
||||
{
|
||||
byte pause_ticks;
|
||||
byte move_ticks;
|
||||
real_vector3d vector;
|
||||
real angle;
|
||||
};
|
||||
|
||||
struct swarm_component_datum
|
||||
{
|
||||
short identifier;
|
||||
short flags;
|
||||
real_point3d position;
|
||||
long surface_index;
|
||||
long combat_target_prop_index;
|
||||
byte attached_to_unit_ticks;
|
||||
byte ground_ticks;
|
||||
byte attack_delay_ticks;
|
||||
byte pad;
|
||||
union
|
||||
{
|
||||
struct swarm_wander_control wander;
|
||||
struct obey_individual_simple_control obey;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Owner assertions should lock, at minimum:
|
||||
|
||||
- `sizeof(swarm_wander_control)==0x14`, vector `+4`, angle `+0x10`;
|
||||
- `sizeof(swarm_component_datum)==0x40`, flags `+2`, position `+4`,
|
||||
surface `+0x10`, target prop `+0x14`, the four bytes `+0x18..+0x1B`, and
|
||||
both union arms `+0x1C`; and
|
||||
- the already-proven composed access
|
||||
`obey.directmovement.vector==+0x28`.
|
||||
|
||||
The retained HCEA generated header spells an explicit `pad[2]` in
|
||||
`swarm_wander_control`. That is a reconstruction convenience, not a named
|
||||
member recovered by DIA, and must not be promoted into the owning schema.
|
||||
|
||||
## Signed flags: independent January corroboration
|
||||
|
||||
January `_code_00005350` (`action_obey_individuals_iterate`, `0x130` padded)
|
||||
zeros exactly `0x24` bytes at component `+0x1C`, then loads the word at `+2`
|
||||
and emits:
|
||||
|
||||
```text
|
||||
xor eax,eax
|
||||
mov ax,word ptr [esi+2]
|
||||
and eax,0xfffffffb
|
||||
or eax,8
|
||||
mov word ptr [esi+2],ax
|
||||
```
|
||||
|
||||
This is the component's `wander`-clear / `obey`-set operation. The frozen
|
||||
Fable measurement records that `short flags` reproduces the
|
||||
`and eax,0xfffffffb` encoding while its prior unsigned `word` spelling emits
|
||||
the different `and eax,0xfffb` form. That code observation corroborates the
|
||||
direct PDB `short`; it is not being used as a spelling-search instruction.
|
||||
|
||||
The committed Fable source must therefore not contribute its flat
|
||||
obey-only component record, even though that local record also uses `short`.
|
||||
Its source SHA-256 is
|
||||
`067b4900d5494c5341ca609337f0d220dedd4f95778a935d601427de96575a59`.
|
||||
|
||||
## Enum owners and provenance tiers
|
||||
|
||||
### `actors.h`: component flags
|
||||
|
||||
Direct `HCEX.pdb` constants authenticate all five spellings and values:
|
||||
|
||||
| enumerator | value |
|
||||
| --- | ---: |
|
||||
| `_swarm_component_attacking_in_melee_bit` | 0 |
|
||||
| `_swarm_component_attached_to_unit_bit` | 1 |
|
||||
| `_swarm_component_wander_bit` | 2 |
|
||||
| `_swarm_component_obey_bit` | 3 |
|
||||
| `_swarm_component_obey_desire_jump_bit` | 4 |
|
||||
|
||||
These belong with `swarm_component_datum.flags` in `actors.h`.
|
||||
`NUMBER_OF_SWARM_COMPONENT_FLAGS` is absent from the PDB and unused by the
|
||||
candidate; do not add it merely because a later extracted DB header has it.
|
||||
|
||||
### `actions.h`: simple-control flags
|
||||
|
||||
Direct `HCEX.pdb` constants authenticate all five spellings and values:
|
||||
|
||||
| enumerator | value |
|
||||
| --- | ---: |
|
||||
| `_obey_simple_directmovement_bit` | 0 |
|
||||
| `_obey_simple_directmovement_update_continuously_bit` | 1 |
|
||||
| `_obey_simple_jump_bit` | 2 |
|
||||
| `_obey_simple_jump_jumped_bit` | 3 |
|
||||
| `_obey_simple_jump_targeted_bit` | 4 |
|
||||
|
||||
They belong beside `obey_individual_simple_control.simple_control_flags` in
|
||||
`actions.h`. `NUMBER_OF_OBEY_SIMPLE_FLAGS` is absent from the PDB and unused,
|
||||
so the proposed owner packet need not invent it.
|
||||
|
||||
### `bipeds.h`: runtime biped flags
|
||||
|
||||
The PDB defines `_biped_datum.flags` as `unsigned long` and directly
|
||||
authenticates the complete six-name set:
|
||||
|
||||
| enumerator | value |
|
||||
| --- | ---: |
|
||||
| `_biped_airborne_bit` | 0 |
|
||||
| `_biped_slipping_bit` | 1 |
|
||||
| `_biped_absolute_movement_bit` | 2 |
|
||||
| `_biped_no_collision_bit` | 3 |
|
||||
| `_biped_movement_passes_through_bipeds_bit` | 4 |
|
||||
| `_biped_limp_body_physics_active_bit` | 5 |
|
||||
|
||||
These belong next to `_biped_datum.flags` in `bipeds.h`.
|
||||
`NUMBER_OF_BIPED_FLAGS` is not returned by DIA and is unnecessary.
|
||||
|
||||
The existing header's `_biped_limping_bit=0` is not an authentic alias:
|
||||
`DIA2Dump -sym _biped_limping_bit` returns no symbol, while bit 0 is directly
|
||||
named `_biped_airborne_bit`. It is also not unused. Current source has five
|
||||
uses in `units.c` (lines 2364, 4219, 4302, 6547, and 10051 at audit time) and
|
||||
one in `players.c` (line 2111). The strongest semantic anchors select
|
||||
`_unit_state_melee_airborne` and `_unit_state_dying_airborne` when the bit is
|
||||
set. A coherent owner repair must rename those six uses to
|
||||
`_biped_airborne_bit`, remove the wrong placeholder, and not retain it as a
|
||||
second same-value name.
|
||||
|
||||
### `ai_scenario_definitions.h`: command-list flags and atom modifiers
|
||||
|
||||
`ai_command_list_definition.flags` is directly `unsigned long` at `+0x20`.
|
||||
The PDB authenticates exactly these five command-list names:
|
||||
|
||||
| enumerator | value |
|
||||
| --- | ---: |
|
||||
| `_ai_command_list_allow_initiative_bit` | 0 |
|
||||
| `_ai_command_list_allow_targeting_bit` | 1 |
|
||||
| `_ai_command_list_disable_looking_bit` | 2 |
|
||||
| `_ai_command_list_disable_communication_bit` | 3 |
|
||||
| `_ai_command_list_disable_falling_damage_bit` | 4 |
|
||||
|
||||
January `action_obey_command_list_setup` independently reads masks
|
||||
`1/2/4/8`, and `action_obey_individual_begin` reads mask `0x10`.
|
||||
`_ai_command_list_manual_structure_bsp_bit=5` and
|
||||
`NUMBER_OF_AI_COMMAND_LIST_FLAGS=6` occur in later extracted DB/Demon
|
||||
material but are not returned by either PDB and are unused by the evidenced
|
||||
eleven-function donor subset. They must not be included in this PDB-grounded
|
||||
packet.
|
||||
|
||||
`ai_command_definition.atom_modifier` is directly a signed `short` at `+2`.
|
||||
The PDB authenticates only
|
||||
`_ai_atom_loop_modifier_until_told_to_advance=1`; January command-end compares
|
||||
the word against 1. The donor's `_ai_atom_loop_modifier_always=0` and count
|
||||
are not needed and have no direct PDB result, so omit them.
|
||||
|
||||
The direct-movement facing domain is the one remaining naming caveat.
|
||||
January `_code_00005f70` proves a signed-short read at simple-control `+8`, an
|
||||
unsigned range check for values `0..3`, and these behaviors:
|
||||
|
||||
- 0: copy the base facing;
|
||||
- 1: negate the base facing;
|
||||
- 2: store the normalized perpendicular;
|
||||
- 3: negate that perpendicular;
|
||||
- any other value: leave the output unchanged.
|
||||
|
||||
This authenticates the values and semantics of the donor spellings
|
||||
`_ai_atom_move_facing_forwards/backwards/left/right`, and the natural owner is
|
||||
the atom-modifier domain in `ai_scenario_definitions.h`. It does **not**
|
||||
authenticate those exact source spellings: DIA returns no such names and the
|
||||
retained HCEA function explicitly records that its enum oracle found none.
|
||||
If descriptive reconstructed enum names are allowed with an explicit
|
||||
provenance comment, those four donor names are semantically credible. If an
|
||||
original-name requirement applies, the private direct-movement/update pair
|
||||
remains withheld; raw integers or a TU-private enum are not acceptable
|
||||
workarounds.
|
||||
|
||||
## Duplicate/facade removal inventory
|
||||
|
||||
One coherent shared-owner trial must address all current production views,
|
||||
not only the donor file:
|
||||
|
||||
| file | current debt | owner-coherent action |
|
||||
| --- | --- | --- |
|
||||
| `source/ai/actors.c` | partial `swarm_component_datum` with unsigned `word flags` and `unknown_tail`; local accessor macro; two local layout typedefs | remove the partial type; consume the owner type; relocate/remove redundant asserts; use the shared typed accessor if installed |
|
||||
| `source/ai/actor_type_infection.c` | local component/wander types (`word flags`, synthetic named `word pad`); local component and obey-simple enums; local biped-airborne enum; local accessor and layout typedefs | remove duplicate types/enums/asserts and consume `actors.h`, `actions.h`, and `bipeds.h` owners |
|
||||
| `source/ai/actor_perception.c` | 0x40 prefix facade `actor_perception_swarm_component_view`; local accessor; raw `TEST_FLAG(...,1)` | remove facade/assert, use `swarm_component_datum`, and name bit 1 `_swarm_component_attached_to_unit_bit` |
|
||||
| `source/units/bipeds.c` | local bit 0 / bit 5 enum | remove it after the complete owner enum lands |
|
||||
| `source/game/player_control.c` | local `_biped_airborne_bit=0` enum | remove it after the owner enum lands |
|
||||
| `source/units/units.c`, `source/game/players.c` | six uses of wrong `_biped_limping_bit` name | migrate all six to direct-PDB `_biped_airborne_bit` |
|
||||
| prospective Fable `source/ai/action_obey.c` body | flat obey-only component, local component/simple/biped/command/modifier enums, local accessor | do not import those definitions; consume the owning headers and shared full-union type |
|
||||
|
||||
`actor_type_infection.c` also copies the field into a local
|
||||
`word component_flags`. DIA proves the **record field** is signed; it does
|
||||
not recover that local variable's source type. Do not retune this local as
|
||||
part of the ownership packet without January function evidence—the header
|
||||
correction alone removes the false record declaration.
|
||||
|
||||
Because `actors.h` already owns `swarm_get`, `swarm_try_and_get`, and the
|
||||
`swarm_component_data` declaration, a single typed `swarm_component_get`
|
||||
macro there is the natural source-owner cleanup for the three current local
|
||||
macros and the future ActionObey caller. Macro ownership is a source-design
|
||||
inference (PDBs do not retain macros), not a recovered original symbol; root
|
||||
may instead retain identical local macros, but the perception facade's return
|
||||
type still must be corrected.
|
||||
|
||||
## Trial boundary and dependency scope
|
||||
|
||||
This audit found 43 direct lexical includers of `actors.h` (42 C files plus
|
||||
`ai_debug.h`), 27 direct includers of `actions.h`, 13 of
|
||||
`ai_scenario_definitions.h`, and 13 of `bipeds.h`. These are only source-text
|
||||
counts, not a substitute for the build dependency graph; the root-owned
|
||||
trial must freeze and compare every actual dependent object and all inherited
|
||||
strict/residual owners.
|
||||
|
||||
The first coherent trial should therefore be one ownership packet:
|
||||
|
||||
1. install the PDB-authenticated full schema and five component bits in
|
||||
`actors.h`;
|
||||
2. remove the three production type facades and migrate perception's raw bit;
|
||||
3. install the five PDB-authenticated obey-simple bits in `actions.h`;
|
||||
4. install the six PDB-authenticated biped bits in `bipeds.h`, remove three
|
||||
local enum bodies, and repair all six wrong bit-0 consumer names;
|
||||
5. install only the PDB-authenticated command-list bits 0..4 and loop-until
|
||||
value 1 in `ai_scenario_definitions.h`;
|
||||
6. decide explicitly whether the four behavior-authenticated but
|
||||
source-name-unproven move-facing enumerators are acceptable; and
|
||||
7. only then compile the unchanged natural ActionObey donor-body subset under
|
||||
real owner headers, with a complete dependent-object/runtime census.
|
||||
|
||||
No enum counts, manual-BSP bit, flat union, synthetic wander pad, raw bit
|
||||
numbers, prefix views, or TU-private fallback enums are part of this
|
||||
recommendation.
|
||||
|
||||
## Evidence read
|
||||
|
||||
- `scratch/fable_action_obey_intake_20260905.md`, SHA-256
|
||||
`587bda8055043f26957944b40939f0a7e9a831957c8cace07e0d3c007238eef6`;
|
||||
- current `actors.h/.c`, `actor_type_infection.c`, `actor_perception.c`,
|
||||
`actions.h`, `ai_scenario_definitions.h`, `bipeds.h/.c`,
|
||||
`player_control.c`, `units.c`, and `players.c`;
|
||||
- the committed Fable `action_obey.c` at
|
||||
`f9dd42218b3325e1b3a63d7860e5309f69fd3d8e`, its saved
|
||||
`scratch/reports/action_obey.md`, and its frozen exactness notes;
|
||||
- complete January disassemblies for `_code_00005350`,
|
||||
`_action_obey_command_list_setup`, `_code_00005290`, `_code_00004fb0`, and
|
||||
`_code_00005f70` from `build/split/source/ai/action_obey.obj`;
|
||||
- direct DIA queries against both PDBs for all types and enumerators recorded
|
||||
above; and
|
||||
- retained HCEA generated headers/functions and Demon command-schema source,
|
||||
used only as corroboration where explicitly identified, never as January
|
||||
original-source proof.
|
||||
@@ -1,83 +0,0 @@
|
||||
# ActionObey shared-schema residual proof (final)
|
||||
|
||||
Date: 2026-09-05
|
||||
|
||||
Scope: the two `runtime_or_owner_changed_REVIEW` sections selected by the frozen
|
||||
58-consumer shared-schema audit. This proof reads only the frozen before/after
|
||||
inventories and objects. It does not read live objects or source, compile,
|
||||
run a gate, refresh a park, or decide packet ownership.
|
||||
|
||||
## Frozen inputs
|
||||
|
||||
- Before inventory SHA-256:
|
||||
`90becfaff10da7f9e549e43d28385da41c37675d51d3c9319347bb7b71600253`
|
||||
- After inventory SHA-256:
|
||||
`b7fef54d4e8030efd58299c5dd290f7e3e9a0ba0c80e8bd8aaa70a929d95c831`
|
||||
- Infection objects:
|
||||
`8bb55ad955ced508c5db6cd768ef437575b3b6e6a83f2140757282854197f531`
|
||||
-> `80caf88f6bc3db25ecffa0488ac480eba0997618be066f5d2cfca6b8fd76de62`
|
||||
- Communication objects:
|
||||
`329718faba04602a5809c17849c23f824ee483b4f854c58bc62d11c7c3e97141`
|
||||
-> `be4f557e04d2b99155594435035bef9705c6e317e85162efe9494d1f5909ed5e`
|
||||
|
||||
## Result
|
||||
|
||||
Both residuals preserve their public ABI, COFF owner/linkage/type/value,
|
||||
section flags/alignment/COMDAT selection, relocation identities and topology,
|
||||
control-flow topology, and observable behavior for a valid call.
|
||||
|
||||
### `_infection_swarm_control`
|
||||
|
||||
- Size remains 3,360 bytes and all 103 relocations map exactly. Thirty-eight
|
||||
relocation source offsets move with the shortened encodings. The six
|
||||
changed internal table destinations map as
|
||||
`1254->1252` three times, `1701->1697` twice, and `1793->1789` once; the
|
||||
table slots themselves remain fixed.
|
||||
- All 130 direct branches and both indirect table jumps map exactly. No branch
|
||||
enters either alignment/trailing-padding interior.
|
||||
- The only executable changes are three `AND EAX, imm32` encodings becoming
|
||||
their sign-extended `imm8` forms: `0x0000fffe -> 0xfffffffe` twice and
|
||||
`0x0000fff7 -> 0xfffffff7` once. Exhaustive evaluation of all 65,536 16-bit
|
||||
flag inputs at all three sites (196,608 comparisons) is exact.
|
||||
- The first two sites explicitly zero EAX before loading AX. At the third
|
||||
site, upper EAX is not assumed zero: only AL is tested and AX is stored;
|
||||
`TEST AL,1` overwrites the `AND` flags before the branch, and each successor
|
||||
fully defines EAX before any full-width read.
|
||||
- The exact allowed padding bytes are asserted, not merely described: old
|
||||
`LEA ESP,[ESP]` becomes `JMP 0x940` plus skipped `LEA EBX,[EBX]`; the old
|
||||
post-`RET` `NOP` becomes post-`RET` `LEA ECX,[ECX]`.
|
||||
- After masking relocation slots, the complete 80-byte `[0xcd0,0xd20)` table
|
||||
and tail are byte-identical, SHA-256
|
||||
`eb8ad26cf1b215d3d0731e00af0d53823547fa6cd4254298bafa1996d58f96c1`.
|
||||
- No runtime/data section was added or lost, no COMMON changed, no definition
|
||||
transition occurred, and the complete function-owner name inventory is
|
||||
unchanged. Shifted compiler-local labels are fully accounted for by the
|
||||
same offset map.
|
||||
|
||||
### `_ai_communication_update_speech_timers`
|
||||
|
||||
- Size remains 672 bytes and all 43 relocation records are byte-for-byte
|
||||
identical.
|
||||
- The only change is the order of adjacent loads in `[0x167,0x16e)`:
|
||||
`DI <- word [EBP+0x10]` and `EBX <- dword [EBP-8]`. They read distinct
|
||||
stack slots, write disjoint registers, and do not touch flags or memory.
|
||||
- Bytes before `0x167` and from `0x16e` onward are identical. All 27 direct
|
||||
branches are identical, two enter at the block boundary `0x167`, the jump at
|
||||
`0x165` rejoins at `0x16e`, no branch targets the strict interior, there are
|
||||
zero indirect jumps, and the block contains zero relocations.
|
||||
- No runtime/data section was added or lost, no COMMON changed, no definition
|
||||
transition occurred, and the complete function-owner name inventory is
|
||||
unchanged.
|
||||
|
||||
This is a frozen-object equivalence proof for these two deltas, not a blanket
|
||||
exception for future schema packets or other compiler-shape changes. It does
|
||||
not replace the root owner's admission, park, build, or stable-gate decision.
|
||||
|
||||
## Artifacts
|
||||
|
||||
- Hardened proof script SHA-256:
|
||||
`b9aa2a4c8b4509c368b9bbd96d5907abd4944202b635edc29c852807e2df74b0`
|
||||
- Final v2 JSON SHA-256:
|
||||
`2a673deafe4714f0ad74ff074feb24d8cb34cb4f87fe6485fbca89d5911c2e4f`
|
||||
- Preserved preliminary v1 JSON SHA-256:
|
||||
`b44e5ed4c6d5e469a0ae821fbd4b91aa6af04393242238d0df7e4670081226c8`
|
||||
@@ -1,121 +0,0 @@
|
||||
# `action_search.obj` exact-match strategy ledger
|
||||
|
||||
## Outcome
|
||||
|
||||
`source/ai/action_search.obj` is strict-exact: all 9 functions and all 4
|
||||
owned `.rdata` COMDAT sections match the January 2002 target in padded size,
|
||||
normalized bytes, relocation count, relocation address/type, and resolved
|
||||
destination/addend.
|
||||
|
||||
The reconstruction began from the HCEA-to-January bridge packet, but every
|
||||
prototype, field offset, constant, call, and source shape was independently
|
||||
gated against the January object. Cross-build evidence was used only as a map;
|
||||
January bytes remained the authority.
|
||||
|
||||
## Final function inventory
|
||||
|
||||
| Function | Padded bytes | Relocations | Result |
|
||||
| --- | ---: | ---: | --- |
|
||||
| `action_search_setup_target` | 128 | 7 | exact |
|
||||
| `action_search_setup_pursuit` | 256 | 10 | exact |
|
||||
| `action_search_setup_undirected` | 112 | 7 | exact |
|
||||
| `action_search_update` | 384 | 9 | exact |
|
||||
| `action_search_flush_position_indices` | 48 | 2 | exact |
|
||||
| `action_search_flush_structure_indices` | 48 | 2 | exact |
|
||||
| `action_search_control` | 336 | 3 | exact |
|
||||
| `action_search_begin` | 144 | 7 | exact |
|
||||
| `action_search_perform` | 848 | 24 | exact |
|
||||
|
||||
## Closeout discoveries
|
||||
|
||||
### `action_search_setup_pursuit`
|
||||
|
||||
The initial reconstruction used an outer eligibility condition plus a nested
|
||||
firing-position guard. That produced the right behavior and size but the wrong
|
||||
cold-epilogue ordering. The exact source is one chained guard containing
|
||||
`firing_position_index != NONE`. VC7 then reuses `BX` for the firing-position
|
||||
index and automatically emits the three January return paths in the correct
|
||||
order. This also satisfies the project's preference for one source-level
|
||||
return.
|
||||
|
||||
General lesson: when several failed predicates share one machine epilogue,
|
||||
write them as one short-circuit condition before trying manual early returns or
|
||||
gotos. The compiler's SSA split may create multiple machine returns even when
|
||||
the C has one return.
|
||||
|
||||
### `action_search_perform`
|
||||
|
||||
Three source details were required:
|
||||
|
||||
1. Keep the maximum-searcher comparison explicitly `short`. Without the cast,
|
||||
integer promotion creates a `movsx` and a 32-bit compare instead of the
|
||||
January 16-bit compare.
|
||||
2. Write the movement dispatch as a flat chain beginning with
|
||||
`if (at_destination)`, followed by the type-0 and type-1 branches. The
|
||||
semantically equivalent nested `if (!at_destination) ... else ...` makes
|
||||
VC7 share the two move-call suffixes in the opposite direction.
|
||||
3. Declare one function-scope `struct prop_datum *prop` and reuse it for both
|
||||
prop lookups. Separate expression temporaries create an EAX/ECX mirror in
|
||||
the examined-pursuit block; the reused named local reproduces January's
|
||||
register coloring exactly.
|
||||
|
||||
The measured rejects included nested versus combined searcher conditions,
|
||||
integer-promoted thresholds, early returns, a `switch`, explicit shared-result
|
||||
gotos, declaration-order changes, `register`, and one- and two-barrier tail
|
||||
experiments. All were reverted when they failed strict comparison.
|
||||
|
||||
## House-rule audit
|
||||
|
||||
- Parameters are one per line.
|
||||
- Typed actor, prop, scenario, and tag-block accessors are used.
|
||||
- Void functions end with explicit `return;` where their exact source permits.
|
||||
- No inline assembly, volatile byte forcing, undefined behavior, compiler flag
|
||||
change, fuzzy credit, or comparator weakening is present.
|
||||
- `action_search_update` retains its early machine-required exit; forcing a
|
||||
single source return would change exact codegen, so this is the documented
|
||||
exception to the preferred single-return rule.
|
||||
|
||||
## Current-campaign revalidation (2026-08-13)
|
||||
|
||||
This atomic lane began at authoritative campaign tip `ea55318e`, where this
|
||||
translation unit was still a 38-line skeleton and reported 0/9 exact functions.
|
||||
Before reconstructing it again, the lane audited all local worktrees and
|
||||
branches and found Claude/Fable's completed but unintegrated object at commit
|
||||
`bd438b42`. Reusing that proven local result was both faster and safer than
|
||||
repeating the source-shape search above.
|
||||
|
||||
The commit was cherry-picked into a new isolated worktree, configured against
|
||||
the installed XDK 3911 compiler and pristine January executable, and rebuilt
|
||||
from source. The hardened comparator independently reproduced every function
|
||||
hash and relocation identity:
|
||||
|
||||
| Function | Padded bytes | Relocations | Normalized SHA-256 |
|
||||
| --- | ---: | ---: | --- |
|
||||
| `action_search_setup_target` | 128/128 | 7/7 | `cbf6d948839e88e8e724d10a38ac71c300c6e37440a51b2882923df9dc0a3cff` |
|
||||
| `action_search_setup_pursuit` | 256/256 | 10/10 | `4347d9f3a5b25001bcdbf6f61d729394de70ebb908f1688e459654c2f10778e3` |
|
||||
| `action_search_setup_undirected` | 112/112 | 7/7 | `dd5c14cc93d1ad3a623a90cc663dd57f974c84bdf8416e95d97219b585f1d933` |
|
||||
| `action_search_update` | 384/384 | 9/9 | `86d23b9bcdbf51d55040b1aeb6342c751a18fdf31f4350606d8b07386b444d64` |
|
||||
| `action_search_flush_position_indices` | 48/48 | 2/2 | `0092a713331f5179dbbff0cc7a9c576e7ebbe07d887f6ba6661da5713a0acd53` |
|
||||
| `action_search_flush_structure_indices` | 48/48 | 2/2 | `828e1700de76a884cac45684d4e9eb16164aac1d8554ab01f9491b715d870b62` |
|
||||
| `action_search_control` | 336/336 | 3/3 | `0152f72402462585a66e38af4f580d73fb27cfebe5d70f432efbd0d105926951` |
|
||||
| `action_search_begin` | 144/144 | 7/7 | `f60a7b46a9e6640afb10e4cc818304c1a6d499f7d9eed99aa42e25b4e29488b9` |
|
||||
| `action_search_perform` | 848/848 | 24/24 | `91321b997bee74aa54c2fea51c3c3ba35c30bedf5e4856f88b259984597d267d` |
|
||||
|
||||
The object owns no `.data` or `.bss`. Its four target-owned `.rdata` COMDATs
|
||||
are the source path and the float constants `0.64f`, `6.25f`, and `0.49f`; all
|
||||
four compare strict exact. Their normalized SHA-256 values are respectively
|
||||
`cfd78efaa8180437a616198604af560523d4c0c77a2106385c170a77946efffd`,
|
||||
`74fdba32aaac063fe5801c661ff89edff6e7852c241a36064ce88505748a5894`,
|
||||
`c1080e69acd873d362d47f9e25351f5237bcf82e3374c88040dc7140aa378747`,
|
||||
and `eeacb7c70a55988e1772bae66236c28b361bba5de119afb4075e752269a6890a`.
|
||||
The `state_data` assertion string is target-external and candidate-owned due to
|
||||
ordinary COMDAT folding; its relocation spelling and bytes are nevertheless
|
||||
strictly resolved at every use by the hardened comparator.
|
||||
|
||||
The source was also manually re-audited against Berth's rules. Parameters are
|
||||
one per line; `void` functions end with explicit `return;`; actor, prop, tag,
|
||||
and tag-block access go through the typed subsystem interfaces; and the one
|
||||
early return in `action_search_update` is retained only because January's
|
||||
machine control flow requires it. No raw object/tag casts, alignment controls,
|
||||
assembly, `volatile`, forced inline, undefined behavior, magic byte forcing,
|
||||
or flag/comparator exception is present.
|
||||
@@ -1,130 +0,0 @@
|
||||
# `action_uncover.obj` credible fuzzy reconstruction and park
|
||||
|
||||
## Result
|
||||
|
||||
`source/ai/action_uncover.obj` now has source for every January function:
|
||||
|
||||
- 8 strict-exact functions;
|
||||
- 1 measured credible residual;
|
||||
- 0 unwritten functions.
|
||||
|
||||
The retained `_action_uncover_perform` is coherent typed C. It has the exact
|
||||
544-byte padded envelope, 164-instruction count, and all 19 January relocation
|
||||
addresses, types, destinations, and addends. Its objdiff score is 98.77778%.
|
||||
Only 43 normalized byte positions differ, all within the contiguous
|
||||
`+0xA2..+0xD3` pursuit-point copy schedule. The eight established exact
|
||||
siblings remain exact, so the object retains 2,112 strict-exact padded code
|
||||
bytes out of 2,656 and has no unwritten byte scope.
|
||||
|
||||
## Evidence and source reconstruction
|
||||
|
||||
The January split object and its disassembly remain authoritative. The frozen
|
||||
ordinary-C candidate from the earlier `jonas/action-uncover-completion-20260828`
|
||||
wave supplied the strongest same-compiler source topology. The following
|
||||
cross-build material was read as corroboration, not as byte authority:
|
||||
|
||||
- HCEA commit `570c83fd9c365dad6f2a3e7041705d5b84c7847c`, whose manually recovered
|
||||
`action_uncover_perform.c` agrees on the selector/change short ABI and the
|
||||
high-level state transitions;
|
||||
- Stian and pastudan retail-Xbox raw-pointer lifts, which corroborate the
|
||||
branch flow and record offsets but are not admissible source;
|
||||
- `punpckhdq/halo`, which still contains only the function stub;
|
||||
- the open Marathon source tree, which has no direct firing-position/uncover
|
||||
homolog and therefore supplies style precedent only.
|
||||
|
||||
The restored body:
|
||||
|
||||
1. asserts that the actor is not a swarm actor;
|
||||
2. gates work on the actor timeslice, passenger state, and completion state;
|
||||
3. constructs the firing-position search from either the pursuit location or
|
||||
the last visible target position;
|
||||
4. selects a candidate and updates the target-visibility or inspected-location
|
||||
state using named line-of-sight and pursuit enums;
|
||||
5. changes the actor's firing position and records failure when no position can
|
||||
be adopted.
|
||||
|
||||
The source uses `boolean`, `real`, `real_point3d`, named enum constants, typed
|
||||
records, and the existing C-series memory helper. It contains no inline
|
||||
assembly, `volatile`, raw byte emission, optimizer directive, artificial
|
||||
dependency, address-placeholder name, or helper call introduced only to steer
|
||||
code generation.
|
||||
|
||||
## Residual boundary
|
||||
|
||||
| Measurement | January | Retained candidate |
|
||||
| --- | ---: | ---: |
|
||||
| Meaningful / padded bytes | 533 / 544 | 533 / 544 |
|
||||
| Instructions | 164 | 164 |
|
||||
| Relocations | 19 | 19 |
|
||||
| Normalized SHA-256 | `ddd3ed044dc0de47ecb6ba83ac683372ff87b3cb7d8fee318d20da5467c39ed8` | `f6c5eb3588f3efccd66611ba0c133b20dc3fb449fad4894f3022b8e9c6f04bd0` |
|
||||
| Objdiff fuzzy score | 100% | 98.77778% |
|
||||
|
||||
January loads all three `real_point3d` dwords before interleaving the
|
||||
independent enable, surface, cluster, and point stores. VC7 lowers the natural
|
||||
aggregate assignment with the same compact source `lea` but alternates the
|
||||
point loads and stores. Code before and after that window realigns exactly.
|
||||
The prior aggregate, scalar, alias, helper, field-order, scope, barrier, and
|
||||
45 documented defined-C topology families are exhausted. Forcing the remaining
|
||||
schedule would require gameplay assembly or artificial source, so the function
|
||||
is parked as `instruction-scheduling` in `config/parked.json`. Reopen only for
|
||||
authenticated January source/local records, a strict same-compiler C donor, or
|
||||
a new natural lifetime fact that preserves the frame, relocations, compact
|
||||
source `lea`, and exact downstream suffix.
|
||||
|
||||
## Prototype ownership and shared-header audit
|
||||
|
||||
`actor_active_select_firing_position` and `actor_change_firing_position` are
|
||||
owned by `actor_firing_position.c`. Their forward-declared record tags and
|
||||
short-width prototypes now live in the closest associated owner header,
|
||||
`actors.h`, rather than in action translation units. The local full work-record
|
||||
definitions remain in their consuming TUs because the owner object is still
|
||||
largely unwritten and moving the large incomplete layouts into a shared header
|
||||
would unnecessarily expose provisional definitions.
|
||||
|
||||
January callee disassembly independently establishes the narrow ABI: the
|
||||
selector returns in `AX`, and the changer consumes the position index through
|
||||
`DI` and returns in `AX`. Existing exact callers were reconciled to `short`
|
||||
locals before removing their duplicate declarations. Rapid same-command-line
|
||||
gates then compared the edited header against the pre-edit header for all 41
|
||||
direct C includers and all five additional C consumers reached through
|
||||
`ai_debug.h`. Every per-function exact/residual/unwritten set was unchanged.
|
||||
In particular:
|
||||
|
||||
- `action_avoid.obj`: 6/6 exact;
|
||||
- `action_fight.obj`: 6/6 exact;
|
||||
- `action_guard.obj`: 15/15 exact;
|
||||
- `units.obj`: 189/189 exact;
|
||||
- `objects.obj`: 121/121 exact.
|
||||
|
||||
The same cleanup removed the final address-style private name from the touched
|
||||
`action_guard.c`. The pinned HCEA PDB authenticates
|
||||
`action_guard_speak_post_combat(long)` in `action_guard.obj`, and the recovered
|
||||
HCEA body corroborates the January function's one-shot post-combat speech
|
||||
semantics. January's PDB omits this private static, so the name is recorded as
|
||||
later-build PDB provenance rather than claimed as January-name-proven. The
|
||||
renamed January function remains strict exact.
|
||||
|
||||
## Ownership and validation
|
||||
|
||||
Relative to the declaration-only baseline, the only new owned production
|
||||
sections are `_action_uncover_perform` itself and its three expected strings
|
||||
(the swarm assertion, target-visibility diagnostic, and pursuit-inspection
|
||||
diagnostic). No helper COMDAT was added. In particular, the candidate symbol
|
||||
table contains no `point_from_line3d` symbol. Direct target comparison reports
|
||||
all 304 target-owned data bytes exact.
|
||||
|
||||
Canonical integration validation completed after regenerating the split and
|
||||
running a full Ninja build:
|
||||
|
||||
- canonical campaign gate: `8 exact / 1 residual / 0 unwritten`;
|
||||
- exact-set comparison: no lost exact sibling;
|
||||
- direct distance audit: 544 bytes, 43 differing normalized positions, 19
|
||||
relocations, identical relocation address and destination sequences;
|
||||
- objdiff: 98.77778% for `_action_uncover_perform`, 100% for all eight siblings,
|
||||
and 100% for target-owned data;
|
||||
- parked-function validator: 1 active, 0 stale, 0 invalid;
|
||||
- fake-match scan across all edited AI source/header files: 0 findings;
|
||||
- full tool suite: 254 passed;
|
||||
- semantic report: 0 unit errors;
|
||||
- common-key exact regression sweep: 0 losses;
|
||||
- `git diff --check`: clean.
|
||||
-136
@@ -1,136 +0,0 @@
|
||||
# `action_uncover.obj` perform ABI reconciliation and scheduler closeout
|
||||
|
||||
## Result
|
||||
|
||||
`source/ai/action_uncover.obj` remains honestly incomplete at 8/9 strict
|
||||
functions and 2,112/2,656 padded code bytes. `_action_uncover_perform` is
|
||||
still absent from the production candidate object; no residual body, owned
|
||||
string, completion label, park, semantic exception, compiler option, or
|
||||
comparator exception is admitted.
|
||||
|
||||
This wave resolves the contradictory selector-width history and exhausts a
|
||||
new, bounded set of ordinary-C copy topologies. The best lawful candidate
|
||||
has the exact 544-byte envelope, all 19 relocations, the same 164-instruction
|
||||
count, and the complete January call/ABI schedule. Its only remaining
|
||||
difference is
|
||||
the already isolated pursuit-point copy scheduler: 43 normalized byte
|
||||
positions in one contiguous `+0xA2..+0xD3` window.
|
||||
|
||||
## Evidence read first
|
||||
|
||||
The current recovery record
|
||||
`docs/object_matching_logs/action_uncover_obj_jonas_recovery.md`, the fuller
|
||||
historical strategy log at commit
|
||||
`1633ccff6d9baa3f01b8e4eb3648b5880932e8be`, and the preserved earlier
|
||||
cross-build closeout log were read in full. The historical log is decisive:
|
||||
January callee disassembly proves all three related types are narrow:
|
||||
|
||||
- `actor_active_select_firing_position` returns `short`;
|
||||
- the receiving `selected_firing_position_index` local is `short`;
|
||||
- `actor_change_firing_position` receives that argument as `short` and returns
|
||||
`short`.
|
||||
|
||||
The 2026-08-26 follow-up in the current recovery record narrowed the selector
|
||||
and local while retaining a `long` consumer parameter. Its resulting
|
||||
sign-extension was therefore an incomplete ABI experiment, not evidence of
|
||||
January-width drift. Repeating the complete three-part short topology makes
|
||||
the call window strict: January and candidate both emit
|
||||
`add esp, 0x18; mov ebx, eax; cmp bx, -1`, with no later sign extension.
|
||||
HCEA independently corroborates the three short types, but January code is the
|
||||
authority.
|
||||
|
||||
## Frozen best candidate
|
||||
|
||||
| Measurement | January | Best ordinary-C candidate |
|
||||
| --- | ---: | ---: |
|
||||
| Meaningful / padded bytes | 533 / 544 | 533 / 544 |
|
||||
| Relocations | 19 | 19 |
|
||||
| Instructions | 164 | 164 |
|
||||
| Normalized SHA-256 | `ddd3ed044dc0de47ecb6ba83ac683372ff87b3cb7d8fee318d20da5467c39ed8` | `f6c5eb3588f3efccd66611ba0c133b20dc3fb449fad4894f3022b8e9c6f04bd0` |
|
||||
|
||||
The immutable best scratch source snapshot is
|
||||
`scratch/_gate_26956.c`, SHA-256
|
||||
`d136beeae2cbe62fa65e46cfc3c16777cd8ae18ad70d2a51977d96feacf6199a`.
|
||||
Its phase-local object is `scratch/_gate_26956.obj`, SHA-256
|
||||
`0ae37faec0fc7446e23ffae6ad373a05a9dec640e0b486ae6c75de768afb41cd`.
|
||||
The January split object is SHA-256
|
||||
`82fd7ef88e212ebca0a7afe5e7eae37eef82054020988046090774865e5bb135`.
|
||||
Raw candidate COFF identity is phase-local because debug records contain the
|
||||
output path; the normalized function hashes are the reproducible identities.
|
||||
|
||||
Every relocation address, type, symbolic destination, and addend agrees. Code
|
||||
before and after the pursuit-copy window realigns exactly. January uses one
|
||||
compact source `lea`, loads all three point dwords, then schedules the stores
|
||||
among the independent surface, cluster, and enable operations. VC7 lowers
|
||||
the best aggregate source with the same compact `lea` but interleaves each
|
||||
point load and store.
|
||||
|
||||
## New compiler probes
|
||||
|
||||
Twenty-five production-neutral variants were compiled from the immutable
|
||||
snapshot. They cover ordinary inline pointer/value aggregate helpers,
|
||||
`const` variants, by-value and return-by-value helpers, scalar/array/union
|
||||
initializers, comma declarations and expressions, branch lifetimes, enclosing
|
||||
aggregate layouts, and supported alias qualifiers. They add the following
|
||||
facts to the historical E01-E20 matrix:
|
||||
|
||||
- aggregate, value-identity, pointer-local, and `const` forms all canonicalize
|
||||
byte-for-byte to the `f6c5eb35...` best candidate;
|
||||
- an inline helper taking a `real_point3d` by value and spelling scalar stores
|
||||
does create January's compact `lea; load x; load y; load z` prefix, but VC7
|
||||
also materializes a 12-byte argument temporary, shifts the frame, duplicates
|
||||
stores, and diverges globally. It remains 544/19 but has normalized hash
|
||||
`3169a4b10565db618e9129673a3ac294cd6c0103cc23345879cde972f58eb6cf`
|
||||
and raw object SHA-256
|
||||
`3c7338bd4dfd682a40fe591a937580be7ddc81674981c570e010a003c65030bb`;
|
||||
- scalar return-by-value helpers remain out of line at 576 bytes / 20
|
||||
relocations;
|
||||
- a named enclosing target subobject rounds from 22 to 24 bytes, shifts every
|
||||
following offset, and yields a nonviable 544/19 object with raw SHA-256
|
||||
`dfde9276e1a93f833186af26bd492ff1e62f09fd7ffef490fc1c2fccc4e343d2`;
|
||||
- XDK 3911 rejects `__restrict`, so this compiler supplies no supported
|
||||
non-alias qualifier to test;
|
||||
- the January PDB module stream for `action_uncover.obj` is only 124 bytes of
|
||||
object/compiler records and contains no local-variable records.
|
||||
|
||||
The research harness is
|
||||
`scratch/uncover_codegen_probe_subagent.py`, SHA-256
|
||||
`176ae1e683a25e6850f75fb98fbae48b81fef7bb4dbee41afb010f371e19d66a`.
|
||||
Scratch artifacts are evidence only and are not tracked or published.
|
||||
|
||||
## Public-source provenance
|
||||
|
||||
The user-supplied repositories were searched at their current public heads and
|
||||
through relevant history.
|
||||
|
||||
- `punpckhdq/halo` is the same build-2342 project, but commit
|
||||
`fc47f9a15a0aea7f0081394c4d66db5c68ab5323` and all 141 reachable commits
|
||||
contain only the original `action_uncover.c` symbol/string stub.
|
||||
- HCEA commit `570c83fd9c365dad6f2a3e7041705d5b84c7847c` contains the strongest typed
|
||||
cross-build reconstruction. Its own comments identify the body as a manual
|
||||
disassembly recovery after decompiler failure; it is not lost Bungie C.
|
||||
- Stian/pastudan target retail Xbox `01.10.12.2276`, not January debug build
|
||||
2342. Their bodies are Ghidra/LLM raw-pointer lifts. The two historical
|
||||
enable/point statement orders are non-admissible and are already subsumed by
|
||||
the measured scalar and field-order families.
|
||||
- Baboon, demon, nimbus, halopc-restored, and xboxrecomp contain no January
|
||||
function source or compiler-spelling record. Xboxrecomp pull request 5 is
|
||||
useful runtime/recompilation infrastructure, but adds no source-provenance
|
||||
control for this scheduler.
|
||||
|
||||
No authentic January/Bungie source or new admissible defined-C spelling was
|
||||
found.
|
||||
|
||||
## Disposition
|
||||
|
||||
The production source is intentionally unchanged: the eight established exact
|
||||
functions remain, `_action_uncover_perform` remains declaration-only, and the
|
||||
two perform-owned strings remain absent. This preserves the atomic/fail-closed
|
||||
boundary and all house rules.
|
||||
|
||||
Do not repeat the historical aggregate, scalar, alias, helper, field-order,
|
||||
scope, barrier, representation-copy, or E01-E20 families, nor the 25 variants
|
||||
above. Reopen only for authentic January source/local records, a same-compiler
|
||||
strict-exact C donor, or a genuinely new defined-C lifetime dependency that
|
||||
retains the compact base `lea` and load-all/store-all schedule without a new
|
||||
temporary, frame change, relocation, or forbidden compiler control.
|
||||
@@ -1,227 +0,0 @@
|
||||
# `action_uncover.obj` Jonas recovery checkpoint
|
||||
|
||||
## Scope and provenance
|
||||
|
||||
This is a bounded partial recovery on authoritative integration commit
|
||||
`2ef097537488b0c71589004a0047dc9a8c02b3e1`. The donor was the clean
|
||||
`action_uncover.c` working-copy artifact in
|
||||
`work/action-search-closeout-20260801` at
|
||||
`10a2244a0d3e6a70b5945995700ff9d9b219dc92`. Its Git blob identity was
|
||||
verified before transplant as
|
||||
`a6c042c1d124b7bd6148ca1b3b34d26244f887db`.
|
||||
|
||||
Only `source/ai/action_uncover.c` is transplanted and adapted. No shared
|
||||
header, configuration, semantic ledger, park entry, status label, existing
|
||||
object log, or Claude-authored Markdown changes. The unit remains
|
||||
`NonMatching`.
|
||||
|
||||
## Frozen-header compatibility bridge
|
||||
|
||||
The donor's dirty worktree also contained an unrelated `ai_debug.h` edit
|
||||
that split `__unknown3C[105]` into `__unknown3C[104]` plus the named
|
||||
`print_uncovering` Boolean. That header edit is not imported.
|
||||
|
||||
The local source instead uses the read-only
|
||||
`ACTION_UNCOVER_DEBUG_PRINTING_ENABLED()` accessor over the already declared
|
||||
`ai_debug.__unknown3C[104]` subobject. The frozen header declares that storage
|
||||
as `char[105]`; the accessor reads the actual one-byte character subobject and
|
||||
uses it only as a truth value, so it does not depend on signedness. A
|
||||
zero-emission compile-time assertion requires the member identity to remain at
|
||||
`+0xA4`. The independent
|
||||
`hs_globals_external.c` registration names that same address
|
||||
`ai_print_uncovering`. There is no cast, pointer arithmetic, write, union
|
||||
overlay, or helper body.
|
||||
|
||||
A controlled A/B XDK build of the original named-field donor and the
|
||||
frozen-header bridge proved the bridge code-neutral before the nonexact body
|
||||
was removed. The final declaration-only build was then independently replayed:
|
||||
all eight retained runtime function sections remain identical to the target in
|
||||
size, normalized bytes, and relocations. The bridge therefore changes only
|
||||
source/debug description, not the credited runtime code or data.
|
||||
|
||||
## Strict code result
|
||||
|
||||
The final forced XDK 3911 measurement reaches the fail-closed donor boundary:
|
||||
8/9 strict-exact target functions, 2,054 meaningful bytes, 2,112 padded
|
||||
bytes, and 71 relocations. Every credited function is exact in padded size,
|
||||
normalized bytes, relocation count, relocation address/type, symbolic
|
||||
destination, and addend.
|
||||
|
||||
| Function | Meaningful | Padded | Relocations | Normalized SHA-256 |
|
||||
| --- | ---: | ---: | ---: | --- |
|
||||
| `_action_uncover_setup_target` | 121 | 128 | 7 | `d2a5512fda5465b171d041acc0a9f229d8923ecbd07f095eb88bf7aebf4f7793` |
|
||||
| `_action_uncover_setup_pursuit` | 247 | 256 | 10 | `9bb3ea855bc4ffb388e7ed9ec451eb2b63944b724094b75ffd87396b498721f2` |
|
||||
| `_action_uncover_control` | 365 | 368 | 5 | `ac833f1fbfe0375f3e11ebd1132430a2c2b6ded9e21549c2d0f9fe09dc231e8d` |
|
||||
| `_action_uncover_flush_position_indices` | 49 | 64 | 2 | `d32f3d33556ecc4034d286cc8dcaef9cbdc100164d9882af21f6eb706b8c8b9a` |
|
||||
| `_action_uncover_flush_structure_indices` | 39 | 48 | 2 | `828e1700de76a884cac45684d4e9eb16164aac1d8554ab01f9491b715d870b62` |
|
||||
| `_action_uncover_modify_color` | 102 | 112 | 4 | `c4db7ebcc9c18e628518139c9c96e35ada43909042d81c6b990e6e6342b659a4` |
|
||||
| `_action_uncover_begin` | 367 | 368 | 18 | `eb0c3080244d12fedb171518d45dee6d575c7cb3c9f1d9f84a26e88c350aec9a` |
|
||||
| `_action_uncover_update` | 764 | 768 | 23 | `47b5885aad0b232ad22cdee9177393a8fd77ac16931ae1c28e9a131dd1ee9356` |
|
||||
|
||||
The source also makes VC7 emit the header-inline
|
||||
`vector_from_points3d`, `magnitude_squared3d`, and
|
||||
`distance_squared3d` COMDATs. They are candidate-owned folded copies, not
|
||||
target functions in this translation unit, and receive zero function credit.
|
||||
|
||||
## Fail-closed residual
|
||||
|
||||
`_action_uncover_perform` is deliberately absent from the candidate object.
|
||||
The source retains only its public prototype. The final candidate symbol
|
||||
table and `_action_uncover_update` relocation inventory contain no perform
|
||||
symbol or relocation; no section, body, helper, or anchor is emitted. There
|
||||
is no perform code credit.
|
||||
|
||||
For provenance, the rejected donor body measured 533 meaningful / 544 padded
|
||||
bytes with 19 relocations. Its normalized SHA-256 was
|
||||
`9c05cfd15a565d4fe76c1dca3670578a42f95173100d3ab91b17cba46fd453cf`,
|
||||
against target
|
||||
`ddd3ed044dc0de47ecb6ba83ac683372ff87b3cb7d8fee318d20da5467c39ed8`.
|
||||
That nonexact body and its exclusively owned strings are not retained.
|
||||
|
||||
The donor already established the two residual scheduling windows: the
|
||||
12-byte pursuit-position copy interleaves loads and stores instead of loading
|
||||
all three dwords first, and the post-select `add esp, 0x18` / `mov ebx,
|
||||
eax` order is exchanged. No tuning is performed after reproducing this
|
||||
measured donor subset.
|
||||
|
||||
## RDATA and ownership boundary
|
||||
|
||||
Ordinary objdiff reports 82.608696% fuzzy RDATA similarity, but no
|
||||
`matched_data` value because the aggregate target boundary is incomplete.
|
||||
The campaign therefore receives 0/304 ordinary data credit. Independent
|
||||
owner-by-owner comparison proves eleven physically owned target COMDATs,
|
||||
218 bytes total, exact in owner identity, logical size, flags/alignment,
|
||||
payload, and zero-relocation shape:
|
||||
|
||||
| Literal/constant owner | Bytes |
|
||||
| --- | ---: |
|
||||
| source path | 35 |
|
||||
| begin-uncover format | 63 |
|
||||
| `pursuit` | 8 |
|
||||
| `target` | 7 |
|
||||
| `un` | 3 |
|
||||
| uncover-done format | 24 |
|
||||
| unknown-reason text | 17 |
|
||||
| location-inspected text | 19 |
|
||||
| persistent-timer format | 20 |
|
||||
| timer-finished format | 18 |
|
||||
| `60.0f` | 4 |
|
||||
|
||||
Another eleven target bytes are the folded
|
||||
`"state_data"` assertion-expression COMDAT. The split action object records
|
||||
that owner undefined, while VC7 emits the normal local select-any copy.
|
||||
Direct comparison with `cachebeta.exe` at the independently recorded symbol
|
||||
file offset 2,371,308 proves both sides are the same eleven bytes with
|
||||
SHA-256
|
||||
`8eeb47459ccd3b18728d86838a1447f42b0207e2ef5ff5996fdaefa90d849878`.
|
||||
This is ownership attribution, not a semantic-data exception. The strict
|
||||
independently proven retained-data boundary is therefore 229/304 bytes.
|
||||
|
||||
The two target-only perform strings total the missing 75 bytes: 31 bytes for
|
||||
the inspected-pursuit message and 44 bytes for the unable-to-see-target
|
||||
message. They disappear with the rejected body. Two candidate-only folded
|
||||
COMDAT definitions total five bytes: the empty string and `30.0f`. They have
|
||||
no target-owned section in this split object and receive zero data credit.
|
||||
|
||||
## Source and policy audit
|
||||
|
||||
The retained reconstruction is readable typed C. Parameters are vertically
|
||||
formatted and every function has an explicit return. It introduces no
|
||||
assembly, volatile scheduling device, force-inline control, optimizer pragma,
|
||||
barrier, undefined aliasing, pointer pun, raw-address arithmetic, data write
|
||||
through the compatibility bridge, byte-forcing expression, or synthetic
|
||||
anchor.
|
||||
|
||||
The frozen `vehicles`, `ai_debug`, `ai_script`, `actions`, and
|
||||
`units` source/config/log surfaces are unchanged from `2ef09753`.
|
||||
|
||||
## Validation
|
||||
|
||||
- full `halobetacache_build` and `libcmt_build`: pass in the 572-edge
|
||||
consolidated build;
|
||||
- semantic audit: 470 units, 3,948 functions evaluated, 3,808 semantic exact,
|
||||
3,869 accepted exact, zero unit errors;
|
||||
- campaign progress: 375/833 objects, 3,856/11,060 functions,
|
||||
467,019/2,198,102 code bytes, and 1,846,712/4,176,062 data bytes;
|
||||
- Halo progress: 273/468 objects, 3,689/7,574 functions,
|
||||
454,105/1,770,166 code bytes, and 1,841,520/3,923,451 data bytes;
|
||||
- object admission: zero candidates, zero revocations; only the inherited
|
||||
unrelated `shell_xbox` contradiction remains;
|
||||
- parked-function audit: 3 active, 0 stale, 0 invalid;
|
||||
- tooling suite: 179/179 tests pass;
|
||||
- configuration remains `NonMatching`; no semantic or parked exception is
|
||||
added.
|
||||
|
||||
Reproducibility identities before the final commit:
|
||||
|
||||
- adapted source Git blob:
|
||||
`a6b3cd4af7259f2268f762f4135ffb48a855e63d`;
|
||||
- adapted source SHA-256:
|
||||
`57735f1cf03c852c642a070c35f0eda684ff7ec0d3d39c38589cf601c209e3cb`;
|
||||
- January target object SHA-256:
|
||||
`82fd7ef88e212ebca0a7afe5e7eae37eef82054020988046090774865e5bb135`.
|
||||
|
||||
The raw candidate COFF hash is intentionally omitted because the timestamped
|
||||
object container changes across forced builds; the per-function normalized
|
||||
hashes above are the reproducible code identities.
|
||||
|
||||
A final committed-state snapshot and forced same-path rebuild/check are
|
||||
performed after the local checkpoint commit. Nothing is pushed.
|
||||
|
||||
## HCEA short-width follow-up (2026-08-26)
|
||||
|
||||
The user-supplied HCEA corpus was refreshed at commit
|
||||
`570c83fd9c365dad6f2a3e7041705d5b84c7847c`. Its
|
||||
`src/blam/ai/action_uncover_perform.c` adds two source facts that were absent
|
||||
from the earlier PDB-only packet: the later-build selector is declared to
|
||||
return `int16_t`, its receiving local is `int16_t`, and the pursuit point is
|
||||
spelled as three indexed `n[]` assignments. These are cross-build hypotheses;
|
||||
January code remains authoritative.
|
||||
|
||||
The clean pre-wave regression manifest is
|
||||
`build/audit/action_uncover_short_return_baseline_20260826.json`, SHA-256
|
||||
`6fefc18d013dd0bd3250b91a0ade399fd2c7a120b058cee97377d3a17508acba`.
|
||||
The preserved preimage object has SHA-256
|
||||
`c9af8e7d7d762362e93db4a0a15d380d8f04ab0f64039755a23bab5d97569999`.
|
||||
All candidate source packets passed VC7 `/Zs` before their ordinary compile.
|
||||
|
||||
Three evidence-separated measurements were made:
|
||||
|
||||
| Candidate | Source SHA-256 | Object SHA-256 | Normalized perform SHA-256 | Result |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| HCEA scalar point copy, short selector return and local | `5e44b5ceeda63c464f4c256582a67a944dd0f0b0edc2c1d9f1135ee2687779d0` | `9607a4d247ce07b7bf7cf76cc64948eba677deef98f19a505fb540ab5f04d509` | `1a81f8957d0af644dc2fb00a9b59b28f127819bed8cdffdb0d7edcf459736a54` | rejected |
|
||||
| Aggregate point copy, short selector return and local | `a86776739746ae14fca69bd4cc90729583e7134cbfbb5b3f53200285b414a6bd` | `597fe15cb624f8a1c06bf0785136b7d2e8644a9c5f4936b34f4a27f15d105ac5` | `1ad7a09e123a93efdc1ea16451b49765676871fb5b11e0ac2ffd2a215fe63e67` | rejected |
|
||||
| Aggregate point copy, January `long` selector return, short local | `5d3c695fb508e98af777e90ec3144c5c8abb2d247033ce373d5bb346bc448aaa` | `24be90ad9b6f332a3e848b5603447f86f05172560f66ec4300a1cdd5a721083d` | `300bba8c0c0ea302c17b22c44e2cbb8da3ad2e8031ee7cb9546e84e4faf5fa56` | rejected |
|
||||
|
||||
The first artifact proves the indexed scalar spelling is not January's
|
||||
source shape. It replaces the compact source-base `lea` with three full
|
||||
displacement loads, adds four bytes before the selector call, and shifts that
|
||||
relocation from `+262` to `+266`.
|
||||
|
||||
The two aggregate artifacts restore the 544-byte envelope and every
|
||||
relocation through the selector call. Narrowing the receiving local does
|
||||
produce January's desired post-call order exactly:
|
||||
`add esp, 0x18; mov ebx, eax`. It also requires a three-byte sign extension
|
||||
before `actor_change_firing_position`, shifting only that final relocation
|
||||
from January `+504` to candidate `+507`. Restoring the selector declaration to
|
||||
`long` does not remove that consumer-side extension. Thus HCEA's short width
|
||||
is later-build drift, not January's exact ABI.
|
||||
|
||||
Both aggregate artifacts retain the other known residual: January loads all
|
||||
three pursuit-point dwords through one compact base `lea` before any of the
|
||||
three destination stores, while VC7 interleaves each load and store. The
|
||||
fresh HCEA source therefore closes the provenance question but supplies no
|
||||
legal-C spelling that satisfies both scheduling windows simultaneously. The
|
||||
prior aggregate, scalar-lifetime, representation-copy, alias, helper, field-
|
||||
order, and scope do-not-repeat list remains in force.
|
||||
|
||||
No rejected perform body or perform-owned data is retained. The source was
|
||||
restored byte-for-byte to its pre-wave Git state and rebuilt normally. The
|
||||
restored object SHA-256 is
|
||||
`558369011d594c5e95ef4b43db52e15ebceddae92b87fa88a95b213a75b4f70d`.
|
||||
The frozen regression gate passes with all eight accepted functions under
|
||||
`still_exact`, no changed nonexact function, no failure, and no warning.
|
||||
`action_uncover.obj` remains 8/9 exact and incomplete. Reopen only for a new
|
||||
January-side source/provenance record or a defined-C control that produces the
|
||||
compact load-all/store-all point copy without introducing the final
|
||||
sign-extension tradeoff.
|
||||
@@ -1,32 +0,0 @@
|
||||
# action_uncover.obj — opus5 150K lane, wave w2 (2026-09-14)
|
||||
|
||||
## Baseline and final
|
||||
|
||||
| gate | result |
|
||||
| --- | --- |
|
||||
| baseline real file | `== exact 8 residual 1 unwritten 0`, guard passes |
|
||||
| final real file (unchanged) | `== exact 8 residual 1 unwritten 0`, guard passes, park drift 0, fake scan 0 leads |
|
||||
|
||||
`git diff --stat -- source/ai/action_uncover.c` is empty. No credit is claimed.
|
||||
|
||||
## `_action_uncover_perform` (parked, instruction-scheduling): SKIPPED-EXHAUSTED
|
||||
|
||||
Target 544 / 19 / `ddd3ed044dc0de47`; candidate 544 / 19 / `f6c5eb3588f3efcc`.
|
||||
|
||||
The residual was re-disassembled. The only differing window is +0xa2..+0xd3:
|
||||
|
||||
- January: `lea edx,[esi+0xb0]`, then loads x/y/z into eax/ecx/edx, then stores x, (surface load), y, (cluster load), enable=1, z, surface, cluster.
|
||||
- VC7: alternates each point load with its store.
|
||||
|
||||
No lever from brief section 9 applies:
|
||||
|
||||
- no call inside the window (store/call order);
|
||||
- equal frame;
|
||||
- no x87;
|
||||
- no inline helper;
|
||||
- one return;
|
||||
- no accessor-binding difference (same compact lea).
|
||||
|
||||
The do-not-repeat lists already cover the remaining candidates: E01-E20, the 25 probe variants of 2026-08-28, and 45 defined-C families. No shape was compiled.
|
||||
|
||||
Reopen criterion (unchanged): authentic January source or local records, or a same-compiler donor for the load-all/store-all copy schedule.
|
||||
-94
@@ -1,94 +0,0 @@
|
||||
# `action_vehicle.obj` evaluate-seat symbol reconciliation (2026-09-13)
|
||||
|
||||
## Scope and ruling
|
||||
|
||||
January target file offset `0x000094C0` is authentically
|
||||
`action_vehicle_evaluate_seat`. `config/symbols.json` therefore maps the old
|
||||
address placeholder `_code_000094c0` to
|
||||
`_action_vehicle_evaluate_seat`. This is a symbol-identity correction only;
|
||||
no function body, prototype, linkage, compiler flag, or source schedule changes
|
||||
in this packet.
|
||||
|
||||
The corrected mapping makes the already reconstructed private caller
|
||||
`action_vehicle_find_impromptu_seat` strict-exact. The evaluate-seat body
|
||||
itself remains fuzzy and receives no exact credit.
|
||||
|
||||
## Same-build name evidence
|
||||
|
||||
The exact January/Halo CE atlas record is:
|
||||
|
||||
```text
|
||||
{"off":"0x4094c0","name":"_action_vehicle_evaluate_seat","lib":"action_vehicle.obj","tier":"exact"}
|
||||
```
|
||||
|
||||
It is record 53 of:
|
||||
|
||||
```text
|
||||
research/halo-symbol-atlas/symbols/halo_ce/4cc87b45f721270392a96f1674ed2b5cd4a7bb4355faeab4531d1cf1884d9520.jsonl
|
||||
```
|
||||
|
||||
The file's SHA-256 is
|
||||
`851802ac508bbcf7cd2896c6cfddd1e0f81510b7b9ef9ea02f39f913c123578e`.
|
||||
Subtracting the image base `0x400000` places the symbol at target file offset
|
||||
`0x94C0`, exactly the `config/symbols.json` record being corrected. The
|
||||
adjacent same-build records independently anchor the object topology:
|
||||
|
||||
- `0x4093B0`: `_action_vehicle_desirable`;
|
||||
- `0x409890`: `_action_vehicle_find_destination`;
|
||||
- `0x40A1B0`: `_action_vehicle_find_impromptu_seat`.
|
||||
|
||||
This direct same-build map, not a behavioral guess, authorizes the production
|
||||
name and relocation identity.
|
||||
|
||||
## Corroboration and limits
|
||||
|
||||
Stian's commit `32a94ebf59066e34057e6e6bfe625d64c61b1be5` introduced the
|
||||
same name after decoding the action-definition table and cross-referencing the
|
||||
call graph. That is useful independent semantic analysis, but it is not
|
||||
original-symbol evidence and was not used alone to admit this mapping.
|
||||
|
||||
The HCEA atlas also contains exact PDB records for
|
||||
`action_vehicle_evaluate_seat`, including `0x83821698` in
|
||||
`567b63bd5f1c5aed0f99b8bc2bb70c9be655d8f6df81d2cbb20c725b33fd6084.jsonl`.
|
||||
Those records corroborate the spelling and role across builds; they are not
|
||||
interchangeable January layout evidence.
|
||||
|
||||
The supplied `h1_tags/*_symbols.exe` images contribute no name proof here.
|
||||
They contain references to missing external PDBs, zero COFF symbols, and no
|
||||
embedded original function-name records. Analysis-generated Ghidra names are
|
||||
not treated as Bungie symbols.
|
||||
|
||||
## Focused verification
|
||||
|
||||
Before target-map regeneration, the universal identity-only scan reports the
|
||||
sole mismatch in the 304-byte caller:
|
||||
|
||||
```text
|
||||
source/ai/action_vehicle::_action_vehicle_find_impromptu_seat
|
||||
@0x0072 target _code_000094c0 + 0
|
||||
ours _action_vehicle_evaluate_seat + 0
|
||||
```
|
||||
|
||||
The ordinary focused gate reports 9 exact, 5 residual, and 3 unwritten
|
||||
functions because its existing split target still carries the old placeholder.
|
||||
Running the same gate with the authenticated in-memory alias
|
||||
`action_vehicle_evaluate_seat=code_000094c0` proves the post-regeneration
|
||||
identity result without disturbing the shared build directory:
|
||||
|
||||
```text
|
||||
EXACT 304 _action_vehicle_find_impromptu_seat
|
||||
residual 976 _code_000094c0 [size 960!=976, relocs 31!=30, sha]
|
||||
== exact 10 residual 5 unwritten 2 (of 17 listed)
|
||||
```
|
||||
|
||||
Thus the caller is strict-exact at 292 meaningful / 304 padded bytes with
|
||||
three matching relocations after the map correction. The current semantic
|
||||
ledger had already admitted those 292 meaningful bytes through its ordinary
|
||||
normalized-code proof despite the unresolved callee spelling. This rename
|
||||
upgrades that existing result to strict relocation identity; it must **not**
|
||||
be booked again as a new 292-byte campaign gain.
|
||||
|
||||
The reconstructed evaluate-seat body is 960 padded bytes against January's
|
||||
976 and has 31 relocations against 30. It remains a best-source fuzzy body,
|
||||
earns zero exact bytes here, and must not be described as closed merely because
|
||||
its original name is now known.
|
||||
@@ -1,220 +0,0 @@
|
||||
# ActionVehicle Fable independent intake (2026-09-06)
|
||||
|
||||
## Decision
|
||||
|
||||
The smallest house-rule-clean packet is **`_action_vehicle_control` only**.
|
||||
Keep `_action_vehicle_begin` held.
|
||||
|
||||
The control packet is three production-source edits for a later owner trial:
|
||||
|
||||
1. Add the donor control body and its TU-local
|
||||
`_action_vehicle_idle_look_type = 4` enum to
|
||||
`source/ai/action_vehicle.c`.
|
||||
2. Add `void action_vehicle_control(long actor_index);` to the genuine owner
|
||||
header, `source/ai/actions.h`, under an `ACTION_VEHICLE.C` prototype block.
|
||||
3. Remove the now-redundant consumer-local declaration of
|
||||
`action_vehicle_control` from `source/ai/actions.c`.
|
||||
|
||||
Do not copy the whole donor file: it also contains the held begin body. No new
|
||||
header include, symbol alias, macro, global, static helper, data owner, or
|
||||
configuration change belongs in the control-only packet.
|
||||
|
||||
`_action_vehicle_begin` is held because its HCEA/prior-rejected contract
|
||||
already had the same three semantics: reset the counter, store
|
||||
`game_time_get()`, and copy `body_position`. Fable's only material source-shape
|
||||
change is the `struct vehicle_state_data *state_data` alias. Exactness therefore
|
||||
comes from a new lvalue topology, not new semantic provenance, and does not
|
||||
satisfy the explicit 2026-08-21 reopen condition. If begin is ever lawfully
|
||||
reopened, it additionally needs the genuine `#include "game/game.h"`; the
|
||||
genuine public declaration of `game_time_get` is `source/game/game.h:171`.
|
||||
|
||||
## Why control is a genuine semantic reconciliation
|
||||
|
||||
The later-build HCEA source uses the wrong January priorities:
|
||||
|
||||
- lock-facing: `_primary_priority_exact_facing` (canonical value 2);
|
||||
- path-present: `_primary_priority_facing` (canonical value 1).
|
||||
|
||||
The January target machine code instead writes 4 and 3. Canonical
|
||||
`source/ai/actors.h:62-66` authentically names those values
|
||||
`_primary_priority_locked_aiming` and `_primary_priority_aiming`. The Fable
|
||||
control body used those two names in its literal first saved source, before any
|
||||
candidate object existed. This is a code-proven semantic correction to the
|
||||
HCEA contract, not an alias-only scheduling retry.
|
||||
|
||||
The remaining contract is also owner-backed:
|
||||
|
||||
- `actors.h:210-214` owns `_direction_specification_movement = 0` and
|
||||
`_direction_specification_vector = 4`;
|
||||
- `actors.h:265` owns `actor_get`, `actors.h:1322` owns `actor_data`, and
|
||||
`actors.h:1157` owns the `actor_path_has_path` prototype
|
||||
(`source/ai/actor_moving.c:310` defines it);
|
||||
- `actions.h:246` owns `struct vehicle_state_data`, and its action-data union at
|
||||
`actions.h:389` owns the `vehicle` arm;
|
||||
- the schema has `lock_facing` at vehicle offset 44 and
|
||||
`destination_facing` at offset 60. January reads actor offsets `0xC8` and
|
||||
`0xD8`, fixing the vehicle arm base at `0x9C` and independently confirming
|
||||
both fields;
|
||||
- `actors.h:582` owns the short `idle_look_type`. The value 4 is present as a
|
||||
TU-local action constant in both `source/ai/action_charge.c:127` and
|
||||
`source/ai/action_avoid.c:35`; no shared idle-look enum exists.
|
||||
|
||||
The target control has 175 meaningful / 176 padded bytes and three
|
||||
relocations: `DIR32 _actor_data` at `+4`, `REL32 _datum_get` at `+17`, and
|
||||
`REL32 _actor_path_has_path` at `+89`. Its normalized SHA-256 is
|
||||
`81612c85cf900b15c2de8ea6d52646f5727a96fbea5e2f13018e6f9613fcd293`.
|
||||
The first code-producing Fable candidate and committed donor object are strict
|
||||
equal on all bytes and relocation identity.
|
||||
|
||||
Both target and candidates define `_action_vehicle_control` as external
|
||||
function symbols (`storage=2`, `type=0x20`, section-relative value 0). There is
|
||||
no private/static implementation symbol to rename.
|
||||
|
||||
## Literal-first versus first-code-producing provenance
|
||||
|
||||
The Fable report's phrase "EXACT - first compile" is accurate only when
|
||||
"compile" means the first code-producing compile:
|
||||
|
||||
- `scratch/_gate_16992.c`, created `2026-09-04T22:46:23.2697770Z`, is the
|
||||
literal first saved source. It already contains the final state alias,
|
||||
locked-aiming/aiming branches, direction choices, and tail stores, but uses
|
||||
undeclared `_idle_look_combat`. No `_gate_16992.obj` is preserved.
|
||||
- `scratch/_gate_35296.c`, created
|
||||
`2026-09-04T22:46:38.1663797Z`, differs only by adding the TU-local
|
||||
`_action_vehicle_idle_look_type = 4` declaration and renaming that one use.
|
||||
`_gate_35296.obj` is the first preserved code-producing object, and control
|
||||
is strict exact there.
|
||||
- The parse/name repair is disclosed. It did not change control flow, field
|
||||
access, priorities, call identity, or emitted runtime data, and is accepted
|
||||
here as pre-code-generation semantic-name closure backed by the two sibling
|
||||
owners above. It must not be described as literal-first-source exact.
|
||||
- `_gate_35296.c` and the committed donor `source/ai/action_vehicle.c` are the
|
||||
same Git blob, `0e89db5e7b3072e1ebb5220f7d5a436428b57d69`.
|
||||
|
||||
The earlier canonical ledger is not superseded silently. It records the
|
||||
one-shot HCEA control miss as normalized SHA
|
||||
`3f96cbf0cdc3a58d1013ac2d44df261acc0d3b68c37ebab639956ddfa1a046ad`
|
||||
against the January hash above and requires new authenticated contract
|
||||
evidence. The 4/3 priority correction is that new evidence for control. No
|
||||
equivalent semantic delta exists for begin.
|
||||
|
||||
## Caller and owner closure
|
||||
|
||||
The complete current source search finds only one consumer:
|
||||
|
||||
- `source/ai/actions.c:764-765` declares control locally;
|
||||
- `source/ai/actions.c:967` stores its address in the vehicle action callback
|
||||
table.
|
||||
|
||||
Current base `actions.obj` carries one `DIR32` reference at `.rdata+536` to an
|
||||
undefined external function symbol `_action_vehicle_control`; January split
|
||||
`actions.obj` carries the same reference at `.rdata+536`. The corresponding
|
||||
begin reference is `.rdata+524`, but begin remains out of scope. No other
|
||||
current base or January split object contains either callback symbol.
|
||||
|
||||
`actions.c` already includes `actions.h`, so moving the control declaration to
|
||||
the genuine header and removing the consumer-local declaration leaves the
|
||||
same signature visible at the callback table. Adding a new `action_vehicle.h`
|
||||
would be an artificial facade and is not admissible. Leaving only a C-local
|
||||
declaration is likewise not owner closure.
|
||||
|
||||
Because `actions.h` is shared, a later trial must freeze and compare all of its
|
||||
actual consumers plus `actions.obj` and `action_vehicle.obj`; this intake did
|
||||
not query Ninja or compile anything.
|
||||
|
||||
## COFF delta
|
||||
|
||||
Against the current canonical base object, `_gate_35296.obj`,
|
||||
`ng_action_vehicle.obj`, and the donor final object all add exactly two named
|
||||
external code owners: begin and control. For the proposed subset, admit only
|
||||
control.
|
||||
|
||||
All seven inherited exact owners remain exact:
|
||||
|
||||
`_action_vehicle_update`, `_action_vehicle_flush_structure_indices`,
|
||||
`_point_from_line2d`, `_distance_squared2d`, `_distance2d`,
|
||||
`_negate_vector2d`, and `_object_get_bounding_sphere`.
|
||||
|
||||
The candidate has no COMMON symbols, BSS section, new writable/read-only data
|
||||
owner, or named static code helper. Its only additional undefineds are
|
||||
`_actor_path_has_path` and `_game_time_get`; the latter belongs solely to the
|
||||
held begin body. Section-symbol `.text` entries with storage 3 are compiler
|
||||
section bookkeeping, not private helpers. The local enum emits no symbol or
|
||||
storage.
|
||||
|
||||
## Pinned artifacts
|
||||
|
||||
Canonical frontier: commit
|
||||
`c2561af50c7fda9c5ea3326b35b4ba10f90d17f5`.
|
||||
|
||||
- January target:
|
||||
`build/split/source/ai/action_vehicle.obj`, 11,826 bytes,
|
||||
SHA-256 `49F00A0115CECF578E51102FC33F665F876A4FAFCB78EE3B53520545406EF769`.
|
||||
- Current canonical candidate baseline:
|
||||
`build/base/source/ai/action_vehicle.obj`, 3,084 bytes,
|
||||
SHA-256 `84FE91F3F197946CA8EC1EED569AFBF77774B44B6F2CEAE4A8540396979E4120`.
|
||||
- Current callback consumer:
|
||||
`build/base/source/ai/actions.obj`, 56,841 bytes,
|
||||
SHA-256 `05FB549A9F707E1E97EE9A44D11CF9AE7AC534752A00ECF22652C60C3374D9D4`;
|
||||
January `build/split/source/ai/actions.obj`, 53,049 bytes,
|
||||
SHA-256 `624BB4506ADFF68E9888A20E44042F28EC7F7E4FDC33115C64C25BEB1270B5B5`.
|
||||
- Canonical source:
|
||||
`source/ai/action_vehicle.c`, SHA-256
|
||||
`22560B33AD7A0250E1ADBD5F500C52DF4102FEAC97E2A280E1E2D1F29428529F`,
|
||||
Git blob `6f689f90311fc56f1f3c0d58c593df81390efdca`.
|
||||
- Canonical owner header:
|
||||
`source/ai/actions.h`, SHA-256
|
||||
`EA1BEC48DFCC5BDAD4DC01137E8C9D4A1F6AA878EE6F3EAEF4D0EF13E64AEE62`,
|
||||
Git blob `5df907fab02c19fd14904ede814923362e2309f5`.
|
||||
- Canonical consumer source:
|
||||
`source/ai/actions.c`, SHA-256
|
||||
`F6347EB2573A36F12CF0C9253DA66504441B8743269E8847FD3866770571D7EC`,
|
||||
Git blob `b1f6be227e232de1a7a5dec92710b5dd8aaea3e6`.
|
||||
- Canonical schema/API source:
|
||||
`source/ai/actors.h`, SHA-256
|
||||
`411A70414C9ED5605A6AB01D14503D7E4B82F2B04BE1D12865CD6D96F45D0B8A`,
|
||||
Git blob `ea715dbedf141721eb4c1bf4585bab5cb7c905be`.
|
||||
- Main prior ledger:
|
||||
`docs/object_matching_logs/action_vehicle_obj_jonas_one_leaf_20260821.md`,
|
||||
SHA-256 `C01350FD8E5C4CBAF48026405D7480E2297FAB4CC307BA0D322693E931627372`.
|
||||
- HCEA begin source:
|
||||
`C:/Users/isabe/Documents/Codex/2026-07-13/i-w/research-cache/halocea-full-blobs-20260830/src/blam/ai/action_vehicle_begin.c`,
|
||||
SHA-256 `4820BFAFAACD281D4F1DBA31312158B158AF55AAD5DAFF4D04E98D247763A3B0`.
|
||||
- HCEA control source:
|
||||
`C:/Users/isabe/Documents/Codex/2026-07-13/i-w/research-cache/halocea-full-blobs-20260830/src/blam/ai/action_vehicle_control.c`,
|
||||
SHA-256 `96F8D95AA428D7AA9F1535A4C2847B8CDA6D97F8C7467E02B883B2C1924C3716`.
|
||||
|
||||
Donor frontier: commit
|
||||
`f9dd42218b3325e1b3a63d7860e5309f69fd3d8e`, parent
|
||||
`96086c9c4c187dd539af13bdaa9252d6e46ad8f6`.
|
||||
|
||||
- Donor report: `scratch/reports/action_vehicle.md`, SHA-256
|
||||
`36D66D460BD2A3F7E0D7C1C623F76A580BA012B22E979AA0A8226E3E3A4043C6`.
|
||||
- Donor facts: `scratch/facts/action_vehicle.md`, SHA-256
|
||||
`24D06EEAC322DE860653F348308B302404CEEF1B0B9DD31C4C7D6A927DAC052F`.
|
||||
- Literal first source: `scratch/_gate_16992.c`, 4,808 bytes, SHA-256
|
||||
`5300FDEB147AA82B39298432663C63F4D7D8E12452B36B386524F7849F7D0F8D`,
|
||||
Git blob `ea342b9e03c72d12584831d6fef4f2a95d3c8f99`.
|
||||
- First code-producing source: `scratch/_gate_35296.c`, 4,869 bytes,
|
||||
SHA-256 `F8F6B69F62B253478B494FE68AF1DABBE987175660E0C41C976EA23F54266F99`,
|
||||
Git blob `0e89db5e7b3072e1ebb5220f7d5a436428b57d69`.
|
||||
- First code-producing object: `scratch/_gate_35296.obj`, 3,651 bytes,
|
||||
SHA-256 `3AAC2DB9C10B2A07E9614358D93F416E5C1FBC7B8EAAD75EA355BF10F6C8E66B`.
|
||||
- Saved later natural object: `scratch/ng_action_vehicle.obj`, 3,651 bytes,
|
||||
SHA-256 `702BFF861ACA3E3D961157DCDBD7D7196A812D5F5EEA3CDFD5A06F9EDD721431`.
|
||||
- Committed donor source: `source/ai/action_vehicle.c`, SHA-256
|
||||
`3E5997DDB9769E1E80682B21E117986BACC2DD1BFD238877ACA392F3A8990A7F`,
|
||||
Git blob `0e89db5e7b3072e1ebb5220f7d5a436428b57d69`.
|
||||
- Donor final object: `build/base/source/ai/action_vehicle.obj`, 3,667 bytes,
|
||||
SHA-256 `0736AE24E228A91848D26B73F8FE86D72EC9B7ACEA9FF42ACA9337D349E4D207`.
|
||||
|
||||
The differing raw candidate-object hashes are explained by producer/debug
|
||||
record paths and timestamps; the hardened function comparison is strict equal
|
||||
for both proposed functions and reports zero inherited losses.
|
||||
|
||||
## Scope statement
|
||||
|
||||
This was read-only over canonical production files and the donor. No source,
|
||||
header, configuration, object, Ninja state, or donor file was changed; no
|
||||
compile, configure, Ninja, or commit command was run. This report is the only
|
||||
new file.
|
||||
-139
@@ -1,139 +0,0 @@
|
||||
# ActionVehicle: Fable control reconciliation (2026-09-06)
|
||||
|
||||
## Scope and verified runtime gate
|
||||
|
||||
The one genuine `action_vehicle_control` correction matches on its first
|
||||
canonical compile and in the ordinary Ninja output. It adds **175 meaningful
|
||||
/ 176 padded exact code bytes** and one function. ActionVehicle advances
|
||||
**7 -> 8 / 17 exact**, with zero residual and nine unwritten functions; it is
|
||||
not a complete object. `action_vehicle_begin` is deliberately not imported.
|
||||
|
||||
The local strict sweep is **6,256 exact / 8,245**, gaining precisely this
|
||||
function with no inherited exact losses. Official local totals are
|
||||
**916,726 / 2,198,102 meaningful exact code bytes**, **6,210 / 11,060 credited
|
||||
functions**, **391 / 833 Matching objects**, and unchanged **2,061,020 /
|
||||
4,176,062 data bytes**. The preceding published geosphere commit is
|
||||
`b90402d960a75d312f2a3895c43850e9cca4ccb8` on both authorized refs.
|
||||
Independent runtime checks now pass. These packet-local numbers precede the
|
||||
independent HUD helper's four meaningful bytes and are not alone a claim of
|
||||
publication. The joint local checkpoint is 916,730 meaningful bytes.
|
||||
|
||||
## Why this is a legitimate contract correction
|
||||
|
||||
The prior 2026-08-21 HCEA-based control attempt used the canonical facing
|
||||
priorities 2/1. January writes **4/3**, independently named in `actors.h` as
|
||||
`_primary_priority_locked_aiming` and `_primary_priority_aiming`. Fable's
|
||||
literal first saved source already contains this semantic correction.
|
||||
The only later pre-emission repair supplies a semantic TU-local name for
|
||||
the proven idle-look value 4; the first preserved code-producing object is
|
||||
exact. That parse/name correction is disclosed, not misrepresented as
|
||||
literal-first-source exactness. Root made no post-compile source variants.
|
||||
|
||||
Begin has no analogous contract correction: its stronger donor shape only
|
||||
introduces a local state pointer over already-correct reset/time/copy logic.
|
||||
Its old source-shape boundary therefore remains held. Do not import the
|
||||
whole donor source or count both claimed 256 padded bytes.
|
||||
|
||||
The independent source/history/COFF intake is
|
||||
`action_vehicle_obj_fable_control_intake_20260906.md`. Root read all seven
|
||||
prior ActionVehicle ledgers, the donor report/facts and complete control
|
||||
diff, the HCEA control body, and the genuine current type/enum/API owners.
|
||||
The user-authorized Fable donor remains read-only at
|
||||
`C:/halo-worktrees/fable-50k-small-families-20260904`, tip
|
||||
`f9dd42218b3325e1b3a63d7860e5309f69fd3d8e`.
|
||||
|
||||
## Genuine owner boundary and full consumer verification
|
||||
|
||||
The sole prerequisite moves the unchanged public `action_vehicle_control`
|
||||
prototype from the consuming `source/ai/actions.c` to the genuine owning
|
||||
`source/ai/actions.h`, under its normal source-family section. The existing
|
||||
header owns `vehicle_state_data`; `actors.h` already supplies typed actor
|
||||
access, priorities, direction kinds and the real `actor_path_has_path` API.
|
||||
No new facade header, duplicate C-local prototype, global, alias, schema,
|
||||
compiler option or configuration exception is introduced.
|
||||
|
||||
Before that edit root captured all **47 actual Ninja consumers**, both
|
||||
sources, the header, January target, configuration and all 572 base hashes.
|
||||
The schema-only build preserves all 6,255 exact functions. Across the full
|
||||
runtime closure, **3,107 sections are unchanged and 53 differ only in
|
||||
compiler-local-label spelling**. There is no lost/changed runtime content,
|
||||
new COMMON storage, or new `point_from_line3d` definition/reference.
|
||||
|
||||
After adding the body, the same inherited 3,160 runtime sections survive.
|
||||
ActionVehicle alone adds the intended control section. It adds no helper,
|
||||
data or BSS owner. Existing helper copies are unchanged, not new progress.
|
||||
The genuine Actions callback table retains its `DIR32` control reference
|
||||
at `.rdata+536`; no artificial caller keeps the body alive.
|
||||
|
||||
Source uses `actor_get`, authentic named fields and enums, a real vector
|
||||
copy, explicit `FALSE` flags and terminal return, with one parameter per
|
||||
line. The locked branch copies the saved facing and skips path lookup;
|
||||
the unlocked branch chooses aiming/movement only when the real path API
|
||||
succeeds. All three branches set idle look and clear the six genuine
|
||||
shoot/movement order flags. No assembly, punning, raw offset, manual
|
||||
helper expansion, register/volatile steering or fake matching is introduced.
|
||||
|
||||
## Exact and frozen identity
|
||||
|
||||
Control target/first/actual agree on normalized SHA-256
|
||||
`81612c85cf900b15c2de8ea6d52646f5727a96fbea5e2f13018e6f9613fcd293`.
|
||||
All three ordered relocations agree: `DIR32 _actor_data` at +4,
|
||||
`REL32 _datum_get` at +17, `REL32 _actor_path_has_path` at +89.
|
||||
The target symbol is an external cdecl public function, not a private
|
||||
address-named body requiring an invented ABI.
|
||||
|
||||
All paths below are canonical-relative:
|
||||
|
||||
| Artifact | SHA-256 |
|
||||
| --- | --- |
|
||||
| `scratch/action-vehicle-fable-control-before-20260906.json` | `fa933a6deb8788e398a06037db7730cace93f8ab47a7efae636b012ae97430d4` |
|
||||
| `scratch/action-vehicle-fable-control-schema-20260906.json` | `6ddf088f8265e4fc707d16a76711df93682d5406965628a4a85bbb22b9462289` |
|
||||
| `scratch/action-vehicle-fable-control-final-20260906.json` | `081017c7ca9d82bf5b240e64a27115ec3d187901a7f2b04f77e291182b8ddf7b` |
|
||||
| frozen January object | `49f00a0115cecf578e51102fc33f665f876a4fafcb78ee3b53520545406ef769` |
|
||||
| `scratch/action-vehicle-fable-control-first-20260906.obj` | `6bc330954c197c8a5dc54c3ed269e39b5d894edafc4d0a4f265b235686b46c2f` |
|
||||
| frozen actual object | `0f80fc38c93779cce5e03eceea3dffa9788386a497300ac6c18e307c66c4f82c` |
|
||||
| frozen ActionVehicle source | `a45f810e182ca07d962da22deb8f9ea0063382650205248d74f66530f7a7725b` |
|
||||
|
||||
Capture: `scratch/action_vehicle_fable_control_capture_20260906.py`.
|
||||
Full runtime comparisons:
|
||||
`scratch/action-vehicle-fable-control-{schema,final}-runtime-20260906/summary.json`.
|
||||
Final stable snapshot:
|
||||
`scratch/action-vehicle-fable-control-final-stable-20260906.json`.
|
||||
Build/gate logs: `scratch/action-vehicle-fable-control-{first,schema-build,final-build}-20260906.log`.
|
||||
|
||||
## Independent execution
|
||||
|
||||
Root reviewed the complete public oracle and its 24 fixture-free tests, then
|
||||
replayed it against the frozen January, first reconciled candidate and actual
|
||||
owner-correct object. All **18 cases pass for each object**, with identical
|
||||
trace SHA-256
|
||||
`87fe79ca103e97d9c177ba4def03ab82e8e91b2ce4c9f41253b761cba9341ed7`.
|
||||
All four pinned real-byte mutants are detected by both semantic checks and
|
||||
target/candidate comparison.
|
||||
|
||||
The oracle checks the entire seeded 0x800-byte actor-memory envelope, precise
|
||||
write order/values, genuine API call order and forwarded handle bits, caller
|
||||
return/argument window, stack balance, clear DF and preserved nonvolatile
|
||||
registers. Locked facing exercises raw vector-word copies, including unusual
|
||||
bit patterns; unlocked paths vary the boolean AL byte while poisoning upper
|
||||
EAX and volatile registers. There is no floating-point arithmetic in this body.
|
||||
|
||||
The envelope is a test boundary, not a `sizeof(actor_datum)` claim. Arbitrary
|
||||
and NONE-shaped handles are forwarding tests with the datum stub returning
|
||||
the modeled owner; they do not claim those handles are valid engine data.
|
||||
The void function's volatile registers are differential observations only.
|
||||
Only genuine `datum_get` and `actor_path_has_path` dependencies are stubbed.
|
||||
|
||||
| Artifact | SHA-256 |
|
||||
| --- | --- |
|
||||
| `tools/audit/action_vehicle_control_runtime_differential.py` | `1f6a27acb013afe57f9ebf43a0020e04fb0720dd56f07653e21dd61ce3af2f79` |
|
||||
| `tools/test_action_vehicle_control_runtime_differential.py` | `cc4f093dec9026fbff5c4495f70ccf3e67915bbed985f46d5952b68478df7327` |
|
||||
| `scratch/action-vehicle-control-public-runtime-root-20260906.json` | `71a50adc3ddea8014a8bf19dc538d970966b47534485db21b017f3e60d455b34` |
|
||||
|
||||
The subsequent ModelAnimations owner-only experiment is completely restored:
|
||||
all 1,523 sections across 13 consumers match the pre-trial state, including
|
||||
Units. No graph implementation was compiled. Its rejected boundary is in
|
||||
`model_animations_obj_fable_node_owner_trial_rejected_20260906.md`.
|
||||
|
||||
Final joint publication checks are recorded in the reconciliation backlog;
|
||||
remote refs must be verified against the resulting commit, not this ledger.
|
||||
@@ -1,128 +0,0 @@
|
||||
# Action-vehicle bounding-sphere recovery (2026-08-27)
|
||||
|
||||
## Result
|
||||
|
||||
The first and only ordinary code-producing candidate makes
|
||||
`_object_get_bounding_sphere` strict exact in
|
||||
`source/ai/action_vehicle.obj`. The object advances from 6/17 to 7/17 exact
|
||||
functions and from 165/4,909 to 294/4,909 meaningful code bytes. It remains
|
||||
`NonMatching`; no data, completion-label, semantic-exception, or
|
||||
parked-function credit is claimed.
|
||||
|
||||
All six inherited exact owners remain exact: `_action_vehicle_update`,
|
||||
`_action_vehicle_flush_structure_indices`, `_point_from_line2d`,
|
||||
`_distance_squared2d`, `_distance2d`, and `_negate_vector2d`.
|
||||
|
||||
## Frozen target and provenance evidence
|
||||
|
||||
January defines an external cdecl
|
||||
`void(long, real_point3d *, real *)` owner with 129 meaningful and 144 padded
|
||||
bytes. It retrieves a typed all-mask object, asserts non-null `center` and
|
||||
`radius` outputs with canonical `objects.h` line metadata 535 and 536, copies
|
||||
the named three-float bounding-sphere center, copies the radius, and returns.
|
||||
|
||||
Its nine relocations are fully fixed: `REL32` to
|
||||
`_object_get_and_verify_type`; two references to the canonical objects-header
|
||||
path literal; references to the `center` and `radius` assertion literals; and
|
||||
two ordered `REL32` pairs to `_display_assert` and `_system_exit`.
|
||||
|
||||
The canonical inline implementation in `source/objects/objects.h`
|
||||
independently supplies the exact signature, typed `object_get` access path,
|
||||
assertion strings and line numbers, named fields, copy order, and explicit
|
||||
terminal return. The HCEA later-build source at commit
|
||||
`570c83fd9c365dad6f2a3e7041705d5b84c7847c` independently corroborates the
|
||||
typed object datum and sphere-field semantics; its source blob is
|
||||
`3bed3193ca7ec40b5f6c81955fc1452b7b5daaf9`. HCEA omits January's assertions
|
||||
and is semantic/type provenance only; January PC COFF remains the sole padded
|
||||
byte and relocation authority.
|
||||
|
||||
The complete Claude campaign tree, Stian sources and verification metadata,
|
||||
all current object ledgers, and all repository revisions were searched before
|
||||
emission. None contains a prior action-vehicle candidate or fixed-point record
|
||||
for this owner. The existing global and HUD copies authenticate the shared
|
||||
contract but do not claim this translation unit's COMDAT ownership.
|
||||
|
||||
The adjacent `_action_vehicle_begin` and `_action_vehicle_control` owners were
|
||||
excluded before emission because the 2026-08-21 action-vehicle ledger already
|
||||
preserves their natural HCEA-backed misses and requires new January evidence
|
||||
before any retry.
|
||||
|
||||
## Retained typed source and house-rule audit
|
||||
|
||||
A translation-unit-local macro rename preserves the canonical inline owner
|
||||
under a private name while allowing January's external COMDAT to be defined
|
||||
from the same typed body:
|
||||
|
||||
```c
|
||||
#define object_get_bounding_sphere object_get_bounding_sphere_inline
|
||||
#include "actors.h"
|
||||
#undef object_get_bounding_sphere
|
||||
|
||||
void object_get_bounding_sphere(
|
||||
long object_index,
|
||||
real_point3d *center,
|
||||
real *radius)
|
||||
{
|
||||
struct object_datum *object = object_get(object_index);
|
||||
|
||||
match_assert("..\\objects\\objects.h", 535, center);
|
||||
match_assert("..\\objects\\objects.h", 536, radius);
|
||||
|
||||
*center = object->object.bounding_sphere_center;
|
||||
*radius = object->object.bounding_sphere_radius;
|
||||
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
Every parameter is on its own line, the C89 declaration precedes statements,
|
||||
the canonical typed object-access macro replaces any raw access cast, the body
|
||||
uses named fields, and the void function ends with an explicit return. It
|
||||
contains no assembly, `register`, `volatile`, optimizer barrier, pragma,
|
||||
intrinsic, attribute, raw address, byte-offset access, pointer/integer
|
||||
reconstruction, pointer or union pun, undefined behavior, synthetic anchor,
|
||||
object patch, comparator exception, or byte forcing.
|
||||
|
||||
## Immutable artifacts and strict comparison
|
||||
|
||||
- Base commit: `6d23d0f7bc976fcd24480411ee6e4878a758d8df`.
|
||||
- Pre-wave source blob: `96eb18be20f7f1aa3e40e65063e9d65f5b57650c`.
|
||||
- Frozen retained source blob: `6f689f90311fc56f1f3c0d58c593df81390efdca`.
|
||||
- January split object SHA-256:
|
||||
`49F00A0115CECF578E51102FC33F665F876A4FAFCB78EE3B53520545406EF769`.
|
||||
- Baseline candidate object SHA-256:
|
||||
`0B473CDE87C91DB8E453A108F777B1138C5556CC44B31303F509AEA8B634B048`.
|
||||
- First-shot object SHA-256:
|
||||
`4A44DE94FA7BC403290B54809F4DC08EAD97D2DC6DC50EC57724626599A96CE4`.
|
||||
- Compiler: Microsoft XDK 3911 CL 13.00.9254.1 with the unchanged natural
|
||||
`/O2 /Oy- /DDEBUG /Dxbox` flags and include graph.
|
||||
|
||||
The hardened comparator proves all 144 padded bytes, all nine relocation
|
||||
addresses, types, destinations, addends, and ownership exact. Target and
|
||||
candidate share normalized SHA-256
|
||||
`65d07f3bd1140a75fa9122ef9ec31f739c4a744a117752b38f576b2493457fef`.
|
||||
The exact-set comparison reports only `_object_get_bounding_sphere` as newly
|
||||
exact, preserves all six inherited exact owners, and reports no loss.
|
||||
|
||||
## One-shot discipline and validation
|
||||
|
||||
`git diff --check` and the production compiler's no-output `/Zs` check passed
|
||||
before emission. Exactly one normal selected-object compiler edge produced the
|
||||
retained artifact. No assertion spelling, macro, field, declaration, include
|
||||
topology, flag, or compiler retry occurred.
|
||||
|
||||
The complete graph and campaign gates pass:
|
||||
|
||||
- 377/833 complete objects overall and 275/468 for Halo;
|
||||
- 511,119/2,198,102 meaningful code bytes and 4,240/11,060 functions overall;
|
||||
- 498,205/1,770,166 Halo code bytes and 4,073/7,574 Halo functions;
|
||||
- data unchanged at 1,836,762/4,176,062 overall;
|
||||
- semantic audit: 470 units, 4,352 functions evaluated, 4,206 semantic exact,
|
||||
4,266 accepted exact, and zero unit errors;
|
||||
- admission: zero candidates, contradictions, or revocations;
|
||||
- parks: three active, zero stale, zero invalid;
|
||||
- tooling tests: 179/179 pass, with only the inherited pytest cache-permission
|
||||
warning.
|
||||
|
||||
No protected source, configuration entry, completion label, push, amend, or
|
||||
history rewrite is involved.
|
||||
@@ -1,112 +0,0 @@
|
||||
# Action-vehicle 2D-distance recovery (2026-08-27)
|
||||
|
||||
## Result
|
||||
|
||||
The first and only ordinary code-producing candidate makes `_distance2d`
|
||||
strict exact in `source/ai/action_vehicle.obj`. The object advances from 4/17
|
||||
to 5/17 exact functions and from 95/4,909 to 132/4,909 meaningful code bytes.
|
||||
It remains `NonMatching`; no data, completion-label, semantic-exception, or
|
||||
parked-function credit is claimed.
|
||||
|
||||
The four inherited exact owners, `_action_vehicle_update`,
|
||||
`_action_vehicle_flush_structure_indices`, `_point_from_line2d`, and
|
||||
`_negate_vector2d`, remain exact.
|
||||
|
||||
## Frozen target and provenance evidence
|
||||
|
||||
January defines an external cdecl `real(real_point2d const *, real_point2d
|
||||
const *)` owner with 37 meaningful and 48 padded bytes. It subtracts the two
|
||||
point components, squares and adds them on the x87 stack, applies `fsqrt`, and
|
||||
returns the result. The function has no relocation.
|
||||
|
||||
The canonical inline implementation in `source/math/real_math.h` supplies the
|
||||
same signature and computes the magnitude of the vector from `a` to `b`. The
|
||||
HCEA later-build source at commit
|
||||
`570c83fd9c365dad6f2a3e7041705d5b84c7847c` independently spells the same two
|
||||
component differences and square root. Its source blob is
|
||||
`3757f43b014e35fe4945b9b678c7857cec58613b`. HCEA supplies semantic and type
|
||||
provenance only; January PC COFF remains the sole padded-byte authority.
|
||||
|
||||
The complete Claude campaign tree, Stian action-vehicle sources and
|
||||
verification metadata, all current ledgers, and all repository revisions were
|
||||
searched before emission. None contains an earlier action-vehicle definition,
|
||||
candidate artifact, or fixed-point record for this owner. The immediately
|
||||
preceding point-from-line ledger explicitly excluded it to preserve the present
|
||||
independent one-shot boundary.
|
||||
|
||||
`_distance3d` and `_distance_squared2d` remained outside this wave. Their
|
||||
different x87 stack shapes require separate frozen evidence and production
|
||||
shots.
|
||||
|
||||
## Retained typed source and house-rule audit
|
||||
|
||||
The existing `actions.h` include brings in the canonical inline math header.
|
||||
A translation-unit-local macro rename retains the inline spelling privately
|
||||
while allowing January's external owner to be defined from the canonical
|
||||
body:
|
||||
|
||||
```c
|
||||
#define distance2d distance2d_inline
|
||||
#include "actions.h"
|
||||
#undef distance2d
|
||||
|
||||
real distance2d(
|
||||
real_point2d const *a,
|
||||
real_point2d const *b)
|
||||
{
|
||||
real_vector2d v;
|
||||
|
||||
return magnitude2d(vector_from_points2d(a, b, &v));
|
||||
}
|
||||
```
|
||||
|
||||
Every parameter is on its own line, the C89 local declaration precedes the
|
||||
statement, typed helpers and named fields provide the arithmetic, and the
|
||||
function ends with an explicit value return. It contains no assembly,
|
||||
`register`, `volatile`, optimizer barrier, pragma, intrinsic, attribute, raw
|
||||
address, byte-offset access, pointer/integer reconstruction, pointer or union
|
||||
pun, undefined behavior, synthetic anchor, object patch, comparator exception,
|
||||
or byte forcing.
|
||||
|
||||
## Immutable artifacts and strict comparison
|
||||
|
||||
- Base commit: `608181dec91c7d657c503d864c115354ed9946a7`.
|
||||
- Pre-wave source blob: `d6af877431ebe5ae8d02c961bb091aa2f6d17683`.
|
||||
- Frozen retained source blob: `8b35c87381770b48b7a6118555b6a60c61b54757`.
|
||||
- January split object SHA-256:
|
||||
`49F00A0115CECF578E51102FC33F665F876A4FAFCB78EE3B53520545406EF769`.
|
||||
- Baseline candidate object SHA-256:
|
||||
`4A2BBD6AFD7DB99DC2636DE3AD3F590B0B52A3D969D450347FB3F0B366BC75F1`.
|
||||
- First-shot object SHA-256:
|
||||
`5901C77965196428278E8290250BAB1B493581466B74A2FF60D5CF70CDEE0285`.
|
||||
- Compiler: Microsoft XDK 3911 CL 13.00.9254.1 with the unchanged natural
|
||||
`/O2 /Oy- /DDEBUG /Dxbox` flags and include graph.
|
||||
|
||||
The hardened comparator proves all 48 padded bytes and zero-relocation
|
||||
identity exact. Target and candidate share normalized SHA-256
|
||||
`3c78450b16a81d94946b346e70e6b6c0b6d43ce353c74c1a18cd64d8e37eff9d`.
|
||||
The exact-set comparison reports only `_distance2d` as newly exact, preserves
|
||||
all four inherited exact owners, and reports no loss.
|
||||
|
||||
## One-shot discipline and validation
|
||||
|
||||
`git diff --check` and the production compiler's no-output `/Zs` check passed
|
||||
before emission. Exactly one normal selected-object compiler edge produced the
|
||||
retained artifact. No expression, helper spelling, declaration, include
|
||||
topology, flag, or compiler retry occurred.
|
||||
|
||||
The complete graph and campaign gates pass:
|
||||
|
||||
- 377/833 complete objects overall and 275/468 for Halo;
|
||||
- 510,957/2,198,102 meaningful code bytes and 4,238/11,060 functions overall;
|
||||
- 498,043/1,770,166 Halo code bytes and 4,071/7,574 Halo functions;
|
||||
- data unchanged at 1,836,762/4,176,062 overall;
|
||||
- semantic audit: 470 units, 4,350 functions evaluated, 4,204 semantic exact,
|
||||
4,264 accepted exact, and zero unit errors;
|
||||
- admission: zero candidates, contradictions, or revocations;
|
||||
- parks: three active, zero stale, zero invalid;
|
||||
- tooling tests: 179/179 pass, with only the inherited pytest cache-permission
|
||||
warning.
|
||||
|
||||
No protected source, configuration entry, completion label, push, amend, or
|
||||
history rewrite is involved.
|
||||
-138
@@ -1,138 +0,0 @@
|
||||
# Action-vehicle 3D-distance fixed point (2026-08-27)
|
||||
|
||||
## Result
|
||||
|
||||
Two separately frozen, evidence-backed waves for `_distance3d` were cleanly
|
||||
rejected. Both candidates preserve all five inherited exact functions in
|
||||
`source/ai/action_vehicle.obj`, match January's 64-byte padded extent, and
|
||||
contain zero relocations, but neither matches the target's x87 instruction
|
||||
schedule. All candidate source was removed and the exact pre-wave source blob
|
||||
was restored.
|
||||
|
||||
The object therefore remains at 5/17 exact functions and 132/4,909 meaningful
|
||||
code bytes. No function, data, completion-label, semantic-exception, or
|
||||
parked-function credit is claimed.
|
||||
|
||||
## Frozen target and provenance evidence
|
||||
|
||||
January defines an external cdecl `real(real_point3d const *, real_point3d
|
||||
const *)` owner with 51 meaningful and 64 padded bytes. It loads the three
|
||||
component differences, squares `x`, then `y`, accumulates those two, squares
|
||||
and accumulates `z`, exchanges the result into the expected x87 slot, applies
|
||||
`fsqrt`, drops the two residual stack values, and returns. It has no
|
||||
relocation. Its normalized SHA-256 is
|
||||
`4cdb6852c1705b5f4af050b829c52d1342a122dccb39f2291f477c6829908b84`.
|
||||
|
||||
The canonical inline implementation in `source/math/real_math.h` supplies the
|
||||
fixed signature and nested vector/magnitude semantics. The independent HCEA
|
||||
later-build source at commit `570c83fd9c365dad6f2a3e7041705d5b84c7847c`
|
||||
spells three scalar differences followed by the left-associated sum of their
|
||||
squares. Its source blob is
|
||||
`0918df559cfdfb35e458f74fc6ebd1592f9eda97`. HCEA is semantic and source-shape
|
||||
provenance only; January PC COFF remains the sole padded-byte authority.
|
||||
|
||||
The complete Claude campaign tree, Stian action-vehicle source and verification
|
||||
metadata, every current ledger, and all repository revisions were searched.
|
||||
None provides another January-authenticated source shape or a prior attempt for
|
||||
this owner.
|
||||
|
||||
## Wave one: canonical nested helper
|
||||
|
||||
The first frozen wave used the canonical inline body under a source-local macro
|
||||
rename:
|
||||
|
||||
```c
|
||||
real distance3d(
|
||||
real_point3d const *a,
|
||||
real_point3d const *b)
|
||||
{
|
||||
real_vector3d v;
|
||||
|
||||
return magnitude3d(vector_from_points3d(a, b, &v));
|
||||
}
|
||||
```
|
||||
|
||||
It emits the same loads, three differences, 64-byte padded extent, and zero
|
||||
relocations, but squares `z`, then `x`, then `y`. Its normalized SHA-256 is
|
||||
`01d7809ae796fc6e9a4a6c2ca73f1e156770bdcff33dd17fc212c50d7279a841`.
|
||||
The immutable candidate object SHA-256 is
|
||||
`995D0A95996A30F24DFA5D09CD6CDE66D1AC8429AD61F14F1B0C93929C95003C`.
|
||||
|
||||
The emitted x87 order and the independent HCEA scalar spelling constituted
|
||||
genuine new evidence, so the canonical source was restored before opening a
|
||||
separate second wave.
|
||||
|
||||
## Wave two: donor-derived scalar topology
|
||||
|
||||
The second frozen wave used the HCEA scalar topology while retaining current
|
||||
typed names and the canonical square-root helper:
|
||||
|
||||
```c
|
||||
real distance3d(
|
||||
real_point3d const *a,
|
||||
real_point3d const *b)
|
||||
{
|
||||
real dx = b->x - a->x;
|
||||
real dy = b->y - a->y;
|
||||
real dz = b->z - a->z;
|
||||
|
||||
return square_root(dx*dx + dy*dy + dz*dz);
|
||||
}
|
||||
```
|
||||
|
||||
It also emits the same loads, differences, extent, and zero-relocation shape,
|
||||
but squares `z`, then `y`, then `x`. Its normalized SHA-256 is
|
||||
`21014f2a01d8cc834186684d7f719a227bf489bc06c34d4890f9b4a862f356f5`.
|
||||
The immutable candidate object SHA-256 is
|
||||
`245CE326C975C10738CA9B8E74CF7ECD07E7A6C419C31DA7029C8A667FA55B61`.
|
||||
|
||||
No further retry is justified by current evidence. Reopen this owner only with
|
||||
a new January-era source donor, compiler intermediate evidence, or a lawful
|
||||
source topology independently explaining the target's exact x87 ownership and
|
||||
drop order.
|
||||
|
||||
## Immutable baseline and restoration
|
||||
|
||||
- Base commit: `6076c6b4953ded466b8f280fc5177999de537d2e`.
|
||||
- Pre-wave and restored source blob:
|
||||
`8b35c87381770b48b7a6118555b6a60c61b54757`.
|
||||
- Canonical-wave source blob:
|
||||
`3dba79474fb4e09b49778ac577f78c27e08654b6`.
|
||||
- Scalar-wave source blob:
|
||||
`1ce486341aed567b5b8b77198d74156e28bf5387`.
|
||||
- January split object SHA-256:
|
||||
`49F00A0115CECF578E51102FC33F665F876A4FAFCB78EE3B53520545406EF769`.
|
||||
- Frozen baseline candidate object SHA-256:
|
||||
`5901C77965196428278E8290250BAB1B493581466B74A2FF60D5CF70CDEE0285`.
|
||||
- Compiler: Microsoft XDK 3911 CL 13.00.9254.1 with the unchanged natural
|
||||
`/O2 /Oy- /DDEBUG /Dxbox` flags and include graph.
|
||||
|
||||
Each wave passed `git diff --check` and a no-output `/Zs` parse before its one
|
||||
normal code-producing compile. Neither used assembly, `register`, `volatile`,
|
||||
optimizer barriers, pragmas, intrinsics, attributes, raw addresses,
|
||||
pointer/integer reconstruction, pointer or union puns, undefined behavior,
|
||||
synthetic anchors, object patches, comparator exceptions, or byte forcing.
|
||||
|
||||
After restoration, the complete exact-set comparison again contains exactly
|
||||
`_action_vehicle_update`, `_action_vehicle_flush_structure_indices`,
|
||||
`_point_from_line2d`, `_distance2d`, and `_negate_vector2d`, with no lost or
|
||||
new owner.
|
||||
|
||||
## Validation
|
||||
|
||||
The restored complete graph and campaign gates pass at the unchanged campaign
|
||||
totals:
|
||||
|
||||
- 377/833 complete objects overall and 275/468 for Halo;
|
||||
- 510,957/2,198,102 meaningful code bytes and 4,238/11,060 functions overall;
|
||||
- 498,043/1,770,166 Halo code bytes and 4,071/7,574 Halo functions;
|
||||
- data at 1,836,762/4,176,062 overall;
|
||||
- semantic audit: 470 units, 4,350 functions evaluated, 4,204 semantic exact,
|
||||
4,264 accepted exact, and zero unit errors;
|
||||
- admission: zero candidates, contradictions, or revocations;
|
||||
- parks: three active, zero stale, zero invalid;
|
||||
- tooling tests: 179/179 pass, with only the inherited pytest cache-permission
|
||||
warning.
|
||||
|
||||
No protected source, configuration entry, completion label, push, amend, or
|
||||
history rewrite is involved.
|
||||
@@ -1,109 +0,0 @@
|
||||
# Action-vehicle squared 2D-distance recovery (2026-08-27)
|
||||
|
||||
## Result
|
||||
|
||||
The first and only ordinary code-producing candidate makes
|
||||
`_distance_squared2d` strict exact in `source/ai/action_vehicle.obj`. The
|
||||
object advances from 5/17 to 6/17 exact functions and from 132/4,909 to
|
||||
165/4,909 meaningful code bytes. It remains `NonMatching`; no data,
|
||||
completion-label, semantic-exception, or parked-function credit is claimed.
|
||||
|
||||
All five inherited exact owners remain exact: `_action_vehicle_update`,
|
||||
`_action_vehicle_flush_structure_indices`, `_point_from_line2d`,
|
||||
`_distance2d`, and `_negate_vector2d`.
|
||||
|
||||
## Frozen target and provenance evidence
|
||||
|
||||
January defines an external cdecl `real(real_point2d const *, real_point2d
|
||||
const *)` owner with 33 meaningful and 48 padded bytes. It loads the two
|
||||
component differences, squares `x`, squares `y`, accumulates them, drops the
|
||||
residual x87 value, and returns. The function has no relocation. Its byte body
|
||||
is exactly the non-square-root prefix of the already accepted adjacent
|
||||
`_distance2d` owner.
|
||||
|
||||
The canonical inline implementation in `source/math/real_math.h` supplies the
|
||||
same signature and computes the squared magnitude of the vector from `a` to
|
||||
`b`. The HCEA later-build source at commit
|
||||
`570c83fd9c365dad6f2a3e7041705d5b84c7847c` independently spells the two
|
||||
component differences and their sum of squares. Its source blob is
|
||||
`c99e46c512b4f42215c6bf887b00b63d51084011`. HCEA supplies semantic and type
|
||||
provenance only; January PC COFF remains the sole padded-byte authority.
|
||||
|
||||
The complete Claude campaign tree, Stian action-vehicle source and verification
|
||||
metadata, all current ledgers, and all repository revisions were searched
|
||||
before emission. None contains an earlier action-vehicle definition,
|
||||
candidate artifact, or fixed-point record for this external owner. Mentions in
|
||||
other object ledgers concern independent translation-unit copies and confer no
|
||||
ownership here.
|
||||
|
||||
## Retained typed source and house-rule audit
|
||||
|
||||
The existing `actions.h` include brings in the canonical inline math header.
|
||||
A translation-unit-local macro rename retains that inline spelling privately
|
||||
while defining January's external owner from the canonical body:
|
||||
|
||||
```c
|
||||
#define distance_squared2d distance_squared2d_inline
|
||||
#include "actions.h"
|
||||
#undef distance_squared2d
|
||||
|
||||
real distance_squared2d(
|
||||
real_point2d const *a,
|
||||
real_point2d const *b)
|
||||
{
|
||||
real_vector2d v;
|
||||
|
||||
return magnitude_squared2d(vector_from_points2d(a, b, &v));
|
||||
}
|
||||
```
|
||||
|
||||
Every parameter is on its own line, the C89 local declaration precedes the
|
||||
statement, typed helpers and named fields carry the arithmetic, and the
|
||||
function ends with an explicit value return. It contains no assembly,
|
||||
`register`, `volatile`, optimizer barrier, pragma, intrinsic, attribute, raw
|
||||
address, byte-offset access, pointer/integer reconstruction, pointer or union
|
||||
pun, undefined behavior, synthetic anchor, object patch, comparator exception,
|
||||
or byte forcing.
|
||||
|
||||
## Immutable artifacts and strict comparison
|
||||
|
||||
- Base commit: `9b60e35bab6620162e3e985960a693e9d48d7dce`.
|
||||
- Pre-wave source blob: `8b35c87381770b48b7a6118555b6a60c61b54757`.
|
||||
- Frozen retained source blob: `96eb18be20f7f1aa3e40e65063e9d65f5b57650c`.
|
||||
- January split object SHA-256:
|
||||
`49F00A0115CECF578E51102FC33F665F876A4FAFCB78EE3B53520545406EF769`.
|
||||
- Baseline candidate object SHA-256:
|
||||
`3502C791766695EDF523005BD35BD478CA266EA3930809B4D1A345C221A6DCC4`.
|
||||
- First-shot object SHA-256:
|
||||
`0B473CDE87C91DB8E453A108F777B1138C5556CC44B31303F509AEA8B634B048`.
|
||||
- Compiler: Microsoft XDK 3911 CL 13.00.9254.1 with the unchanged natural
|
||||
`/O2 /Oy- /DDEBUG /Dxbox` flags and include graph.
|
||||
|
||||
The hardened comparator proves all 48 padded bytes and zero-relocation
|
||||
identity exact. Target and candidate share normalized SHA-256
|
||||
`e12f5936181ec0b4f78951a003a60fa0a613f8f5345003e293f2b3a4a180c4f2`.
|
||||
The exact-set comparison reports only `_distance_squared2d` as newly exact,
|
||||
preserves all five inherited exact owners, and reports no loss.
|
||||
|
||||
## One-shot discipline and validation
|
||||
|
||||
`git diff --check` and the production compiler's no-output `/Zs` check passed
|
||||
before emission. Exactly one normal selected-object compiler edge produced the
|
||||
retained artifact. No expression, helper spelling, declaration, include
|
||||
topology, flag, or compiler retry occurred.
|
||||
|
||||
The complete graph and campaign gates pass:
|
||||
|
||||
- 377/833 complete objects overall and 275/468 for Halo;
|
||||
- 510,990/2,198,102 meaningful code bytes and 4,239/11,060 functions overall;
|
||||
- 498,076/1,770,166 Halo code bytes and 4,072/7,574 Halo functions;
|
||||
- data unchanged at 1,836,762/4,176,062 overall;
|
||||
- semantic audit: 470 units, 4,351 functions evaluated, 4,205 semantic exact,
|
||||
4,265 accepted exact, and zero unit errors;
|
||||
- admission: zero candidates, contradictions, or revocations;
|
||||
- parks: three active, zero stale, zero invalid;
|
||||
- tooling tests: 179/179 pass, with only the inherited pytest cache-permission
|
||||
warning.
|
||||
|
||||
No protected source, configuration entry, completion label, push, amend, or
|
||||
history rewrite is involved.
|
||||
@@ -1,108 +0,0 @@
|
||||
# Action-vehicle vector-negation recovery (2026-08-27)
|
||||
|
||||
## Result
|
||||
|
||||
The first and only ordinary code-producing candidate makes
|
||||
`_negate_vector2d` strict exact in `source/ai/action_vehicle.obj`. The object
|
||||
advances from 2/17 to 3/17 exact functions and from 35/4,909 to 60/4,909
|
||||
meaningful code bytes. It remains `NonMatching`; no data, completion-label,
|
||||
semantic-exception, or parked-function credit is claimed.
|
||||
|
||||
Both inherited exact owners, `_action_vehicle_update` and
|
||||
`_action_vehicle_flush_structure_indices`, remain exact.
|
||||
|
||||
## Frozen target and provenance evidence
|
||||
|
||||
January defines an external cdecl `real_vector2d *(real_vector2d const *,
|
||||
real_vector2d *)` owner with 25 meaningful and 32 padded bytes. It loads the
|
||||
two source floats in order, negates each with x87 `fchs`, stores them to the
|
||||
corresponding result fields, leaves the result pointer in `EAX`, and returns.
|
||||
The function has no relocation.
|
||||
|
||||
The canonical inline implementation in `source/math/real_math.h` independently
|
||||
supplies the exact signature and named-field semantics. The HCEA later-build
|
||||
source at commit `570c83fd9c365dad6f2a3e7041705d5b84c7847c` independently performs the same
|
||||
two component negations and returns the result pointer. Its source blob is
|
||||
`2c138a6375cc6957f91a3af3756ff5309f12518b`. HCEA supplies semantic and type
|
||||
provenance only; January PC COFF remains the sole padded-byte authority.
|
||||
|
||||
The complete Claude campaign tree at
|
||||
`0e1fc785b7f5fb8c8d6fec8cae667005aa663957`, Stian sources and verification
|
||||
metadata, all current object ledgers, and all repository revisions were
|
||||
searched before emission. They contain no earlier action-vehicle definition,
|
||||
candidate artifact, or fixed-point record for this owner. The broader Claude
|
||||
and Stian action-vehicle reconstructions concern larger actor-action bodies and
|
||||
do not alter this standalone math leaf's signature or ownership.
|
||||
|
||||
## Retained typed source and house-rule audit
|
||||
|
||||
The existing `actions.h` include brings in the canonical inline math header.
|
||||
A translation-unit-local macro rename keeps that inline implementation
|
||||
available as `negate_vector2d_inline` while allowing January's external owner
|
||||
to be defined naturally:
|
||||
|
||||
```c
|
||||
#define negate_vector2d negate_vector2d_inline
|
||||
#include "actions.h"
|
||||
#undef negate_vector2d
|
||||
|
||||
real_vector2d *negate_vector2d(
|
||||
real_vector2d const *a,
|
||||
real_vector2d *result)
|
||||
{
|
||||
result->i = -a->i;
|
||||
result->j = -a->j;
|
||||
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
Every parameter is on its own line, the implementation uses the named typed
|
||||
fields, and the function ends with an explicit value return. It contains no
|
||||
assembly, `register`, `volatile`, optimizer barrier, pragma, intrinsic,
|
||||
attribute, raw address, byte-offset access, pointer/integer reconstruction,
|
||||
pointer or union pun, undefined behavior, synthetic anchor, object patch,
|
||||
comparator exception, or byte forcing.
|
||||
|
||||
## Immutable artifacts and strict comparison
|
||||
|
||||
- Base commit: `21ab835f9748f2423d8c6a77c0da99f2b42eebc3`.
|
||||
- Pre-wave source blob: `21e056ab7bf30cb7f746e8a610ca15146a4785ae`.
|
||||
- Frozen retained source blob: `18146aae0ffe9fe419384a27c204a04aa7d276f0`.
|
||||
- January split object SHA-256:
|
||||
`49F00A0115CECF578E51102FC33F665F876A4FAFCB78EE3B53520545406EF769`.
|
||||
- Baseline candidate object SHA-256:
|
||||
`E87C78FD8A92B66B61018183132ED60DD1CEE3AAB8CCF80FF471F9B8818CF276`.
|
||||
- First-shot object SHA-256:
|
||||
`128B7726809D6A1814973851CB71E5F5B1023F34D4A012AD297482FA1B3EDF5D`.
|
||||
- Compiler: Microsoft XDK 3911 CL 13.00.9254.1 with the unchanged natural
|
||||
`/O2 /Oy- /DDEBUG /Dxbox` flags and include graph.
|
||||
|
||||
The hardened comparator proves all 32 padded bytes and zero-relocation
|
||||
identity exact. Target and candidate share normalized SHA-256
|
||||
`5a29b0bda878f7b2a152c71c0056cd52ba442629e5177fb7f7617ac83bc3eed3`.
|
||||
The exact-set comparison reports only `_negate_vector2d` as newly exact,
|
||||
preserves both inherited exact owners, and reports no loss.
|
||||
|
||||
## One-shot discipline and validation
|
||||
|
||||
`git diff --check` and the production compiler's no-output `/Zs` check passed
|
||||
before emission. Exactly one normal selected-object compiler edge produced the
|
||||
retained artifact. No field spelling, statement order, include topology,
|
||||
flag, or compiler retry occurred.
|
||||
|
||||
The complete graph and campaign gates pass:
|
||||
|
||||
- 377/833 complete objects overall and 275/468 for Halo;
|
||||
- 510,885/2,198,102 meaningful code bytes and 4,236/11,060 functions overall;
|
||||
- 497,971/1,770,166 Halo code bytes and 4,069/7,574 Halo functions;
|
||||
- data unchanged at 1,836,762/4,176,062 overall;
|
||||
- semantic audit: 470 units, 4,348 functions evaluated, 4,202 semantic exact,
|
||||
4,262 accepted exact, and zero unit errors;
|
||||
- admission: zero candidates, contradictions, or revocations;
|
||||
- parks: three active, zero stale, zero invalid;
|
||||
- tooling tests: 179/179 pass, with only the inherited pytest cache-permission
|
||||
warning.
|
||||
|
||||
No protected source, configuration entry, completion label, push, amend, or
|
||||
history rewrite is involved.
|
||||
@@ -1,124 +0,0 @@
|
||||
# `action_vehicle.obj` Jonas one-leaf wave
|
||||
|
||||
## Result
|
||||
|
||||
This bounded source-only wave starts from authoritative integration commit
|
||||
`d3453bd46972f3c24148b2de14f495286fa3637c`. The three permitted HCEA-backed
|
||||
action-vehicle bodies were emitted together in exactly one natural candidate
|
||||
compile. `_action_vehicle_flush_structure_indices` was independently strict
|
||||
and is retained. `_action_vehicle_begin` and `_action_vehicle_control` missed
|
||||
and were removed immediately, without a spelling, declaration, control-flow,
|
||||
or compiler-control retry. The pre-existing exact `_action_vehicle_update`
|
||||
body and bytes are unchanged.
|
||||
|
||||
`action_vehicle.obj` advances from 1/17 to 2/17 exact functions and remains
|
||||
`NonMatching`.
|
||||
|
||||
| Retained function | Meaningful | Padded | Relocations | Normalized SHA-256 |
|
||||
| --- | ---: | ---: | ---: | --- |
|
||||
| `_action_vehicle_flush_structure_indices` | 34 | 48 | 2 | `0463c71d743e4bc0945ec5b28c91d1650764463a866ff5e552074a88f4ad1130` |
|
||||
| **Wave gain** | **34** | **48** | **2** | |
|
||||
|
||||
The hardened COFF comparator proves identical padded bytes and exact
|
||||
relocation addresses, types, destinations, and addends. The object now reports
|
||||
35/4,909 meaningful code bytes and two exact functions. The target's remaining
|
||||
fifteen functions and all 116 non-code bytes stay outside this wave's credit.
|
||||
|
||||
## Provenance and signatures
|
||||
|
||||
- Baseline `source/ai/action_vehicle.c` blob:
|
||||
`77f976dc9617cb72d35c768e2fa2b839be7d7ad5`.
|
||||
- Retained source blob/committed-blob SHA-256:
|
||||
`21e056ab7bf30cb7f746e8a610ca15146a4785ae` /
|
||||
`ef2f07e6e1a4ede19ce03b834a6de720c9cf1eca465299f3e80e39b1c3286308`.
|
||||
- January executable SHA-256:
|
||||
`4cc87b45f721270392a96f1674ed2b5cd4a7bb4355faeab4531d1cf1884d9520`.
|
||||
- January split-object SHA-256:
|
||||
`49f00a0115cecf578e51102fc33f665f876a4fafcb78ee3b53520545406ef769`.
|
||||
- Clean HCEA semantic donor commit:
|
||||
`570c83fd9c365dad6f2a3e7041705d5b84c7847c`. Its exact-name
|
||||
`src/blam/ai/action_vehicle_begin.c`,
|
||||
`src/blam/ai/action_vehicle_flush_structure_indices.c`, and
|
||||
`src/blam/ai/action_vehicle_control.c` files supply the three natural typed
|
||||
behaviors. The retained donor file's blob is
|
||||
`99133bb4ae11f72755ea63cc95f4fede8c9d4182`.
|
||||
- January PC disassembly independently fixes the 32-bit actor datum handle,
|
||||
`actor_get`/`datum_get` access path, destination-surface field store, exact
|
||||
call identities, code extents, padding, and relocation ownership. January
|
||||
COFF remains authoritative for acceptance.
|
||||
- Compiler: Microsoft 32-bit C/C++ Optimizing Compiler `13.00.9254.1` for
|
||||
80x86, SHA-256
|
||||
`483e00c47bb08d699475a642bcff15b5b2036350b31c540e88a506baf101da11`,
|
||||
with the repository's unchanged XDK 3911 command and flags.
|
||||
|
||||
The retained signature is:
|
||||
|
||||
```c
|
||||
void action_vehicle_flush_structure_indices(
|
||||
long actor_index);
|
||||
```
|
||||
|
||||
Existing `actors.h` and `actions.h` own the typed actor/action layout and
|
||||
`actor_get` contract. Existing `cseries.h` owns `NONE`. No shared-header or
|
||||
storage repair is needed.
|
||||
|
||||
## Authenticated behavior and one-shot rejection record
|
||||
|
||||
The retained body resolves the full 32-bit actor handle through `actor_get`
|
||||
and invalidates
|
||||
`actor->state.action_data.vehicle.destination_surface_index` with `NONE`.
|
||||
Its target relocations are `DIR32 _actor_data` at `+8` and
|
||||
`REL32 _datum_get` at `+15`.
|
||||
|
||||
All three candidates were compiled together once. The following two misses
|
||||
were removed without retry:
|
||||
|
||||
| Rejected function | Target meaningful / padded / relocs | Target hash | First natural candidate |
|
||||
| --- | ---: | --- | --- |
|
||||
| `_action_vehicle_begin` | `76 / 80 / 3` | `5e5ac406a3045fd7df7a8414f08608cd1ece5bd940ea167941fb293bd192a8f0` | `80 / 3`, SHA `fef3ce0d9fc229b139957cfc30fdcc6d1a4a212be1536f2ebc864411f2046c65`; the relocation addresses and identities are equal, but normalized instruction bytes differ. |
|
||||
| `_action_vehicle_control` | `175 / 176 / 3` | `81612c85cf900b15c2de8ea6d52646f5727a96fbea5e2f13018e6f9613fcd293` | `176 / 3`, SHA `3f96cbf0cdc3a58d1013ac2d44df261acc0d3b68c37ebab639956ddfa1a046ad`; the relocation addresses and identities are equal, but normalized instruction bytes differ. |
|
||||
|
||||
For `_action_vehicle_begin`, the common relocations are `DIR32 _actor_data`
|
||||
at `+8`, `REL32 _datum_get` at `+16`, and `REL32 _game_time_get` at `+35`.
|
||||
For `_action_vehicle_control`, they are `DIR32 _actor_data` at `+4`,
|
||||
`REL32 _datum_get` at `+17`, and `REL32 _actor_path_has_path` at `+89`.
|
||||
Both rejected COMDATs and their candidate-only includes/constants are absent
|
||||
from the final object. Reopen either body only with independently preserved
|
||||
January source or a newly authenticated ordinary-C contract; do not tune from
|
||||
the rejected objects.
|
||||
|
||||
## Policy, scope, and validation
|
||||
|
||||
Only `source/ai/action_vehicle.c` and this new Jonas-owned ledger are changed.
|
||||
No shared header, storage definition, data section, configuration, semantic
|
||||
exception, parked record, completion label, frozen-five source, pre-existing
|
||||
Markdown, or Claude-owned file is edited.
|
||||
|
||||
The retained source is readable typed C. It contains no assembly, raw address
|
||||
or byte-offset dereference, pointer/integer reconstruction, pointer or union
|
||||
pun, inactive-union access, undefined overflow, volatile scheduling device,
|
||||
force-inline annotation, optimizer pragma/barrier, synthetic anchor, or
|
||||
object-byte forcing. The final COFF's only action-vehicle code symbols are the
|
||||
pre-existing `_action_vehicle_update` and retained
|
||||
`_action_vehicle_flush_structure_indices`; it adds no owned storage.
|
||||
|
||||
- Complete 569-edge `halobetacache_build` and `libcmt_build`: pass.
|
||||
- Direct hardened comparison: both `_action_vehicle_update` and
|
||||
`_action_vehicle_flush_structure_indices` pass; both rejected symbols are
|
||||
absent from the final COFF symbol table.
|
||||
- Semantic audit: 470 units, 4,053 functions evaluated, 3,913 semantic exact,
|
||||
101 hidden exact / 61,876 hidden code bytes, 3,974 accepted exact, and zero
|
||||
unit errors.
|
||||
- Campaign progress: 375/833 complete objects, 3,961/11,060 exact functions,
|
||||
475,672/2,198,102 meaningful code bytes, and
|
||||
1,835,088/4,176,062 matched data bytes. This wave adds one function and 34
|
||||
meaningful bytes with no data increase.
|
||||
- Admission audit: zero candidates and zero revocations; only the inherited
|
||||
`source/shell/shell_xbox` completion-label contradiction remains.
|
||||
- Parked validation: three active, zero stale, and zero invalid entries.
|
||||
- Complete tooling suite: 179/179 tests pass; `git diff --check` is clean.
|
||||
|
||||
A clean committed-state snapshot followed by deletion and forced rebuilding
|
||||
of `action_vehicle.obj` is the final same-path reproducibility proof. The
|
||||
post-rebuild hardened comparison remains strict for both accepted functions.
|
||||
No push is performed.
|
||||
@@ -1,112 +0,0 @@
|
||||
# Action-vehicle point-from-line recovery (2026-08-27)
|
||||
|
||||
## Result
|
||||
|
||||
The first and only ordinary code-producing candidate makes
|
||||
`_point_from_line2d` strict exact in `source/ai/action_vehicle.obj`. The object
|
||||
advances from 3/17 to 4/17 exact functions and from 60/4,909 to 95/4,909
|
||||
meaningful code bytes. It remains `NonMatching`; no data, completion-label,
|
||||
semantic-exception, or parked-function credit is claimed.
|
||||
|
||||
The three inherited exact owners, `_action_vehicle_update`,
|
||||
`_action_vehicle_flush_structure_indices`, and `_negate_vector2d`, remain
|
||||
exact.
|
||||
|
||||
## Frozen target and provenance evidence
|
||||
|
||||
January defines an external cdecl
|
||||
`real_point2d *(real_point2d const *, real_vector2d const *, real,
|
||||
real_point2d *)` owner with 35 meaningful and 48 padded bytes. It computes the
|
||||
two components in order as `t*v + p`, stores them to the result point, leaves
|
||||
the result pointer in `EAX`, and returns. The function has no relocation.
|
||||
|
||||
The canonical inline implementation in `source/math/real_math.h` independently
|
||||
supplies the exact signature, parameter order, named fields, arithmetic order,
|
||||
and return value. Its source blob is
|
||||
`39a62c3da5b6a9003dfeb420ed554d1718596541`. January PC COFF remains the sole
|
||||
padded-byte authority.
|
||||
|
||||
The complete Claude campaign tree, HCEA and Stian action-vehicle sources and
|
||||
metadata, all current ledgers, and all repository revisions were searched
|
||||
before emission. None contains a prior action-vehicle definition, candidate
|
||||
artifact, or fixed-point record for this owner. The existing path-structure
|
||||
ledgers mention the same canonical inline helper only as a spelling option in
|
||||
other translation units; they neither define nor claim this external owner.
|
||||
|
||||
The adjacent `_distance2d` and `_distance3d` leaves were deliberately excluded
|
||||
from this wave because their nested magnitude helpers introduce separate x87
|
||||
stack-scheduling evidence. This wave froze only the direct arithmetic leaf.
|
||||
|
||||
## Retained typed source and house-rule audit
|
||||
|
||||
The existing `actions.h` include brings in the canonical inline math header.
|
||||
A translation-unit-local macro rename retains that inline owner under a private
|
||||
name while allowing January's external function to be defined naturally:
|
||||
|
||||
```c
|
||||
#define point_from_line2d point_from_line2d_inline
|
||||
#include "actions.h"
|
||||
#undef point_from_line2d
|
||||
|
||||
real_point2d *point_from_line2d(
|
||||
real_point2d const *p,
|
||||
real_vector2d const *v,
|
||||
real t,
|
||||
real_point2d *result)
|
||||
{
|
||||
result->x = t*v->i + p->x;
|
||||
result->y = t*v->j + p->y;
|
||||
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
Every parameter is on its own line, the implementation uses named typed
|
||||
fields, and the function ends with an explicit value return. It contains no
|
||||
assembly, `register`, `volatile`, optimizer barrier, pragma, intrinsic,
|
||||
attribute, raw address, byte-offset access, pointer/integer reconstruction,
|
||||
pointer or union pun, undefined behavior, synthetic anchor, object patch,
|
||||
comparator exception, or byte forcing.
|
||||
|
||||
## Immutable artifacts and strict comparison
|
||||
|
||||
- Base commit: `dccc548cc21c1dfc6a3ab8e1083888794141e506`.
|
||||
- Pre-wave source blob: `18146aae0ffe9fe419384a27c204a04aa7d276f0`.
|
||||
- Frozen retained source blob: `d6af877431ebe5ae8d02c961bb091aa2f6d17683`.
|
||||
- January split object SHA-256:
|
||||
`49F00A0115CECF578E51102FC33F665F876A4FAFCB78EE3B53520545406EF769`.
|
||||
- Baseline candidate object SHA-256:
|
||||
`128B7726809D6A1814973851CB71E5F5B1023F34D4A012AD297482FA1B3EDF5D`.
|
||||
- First-shot object SHA-256:
|
||||
`4A2BBD6AFD7DB99DC2636DE3AD3F590B0B52A3D969D450347FB3F0B366BC75F1`.
|
||||
- Compiler: Microsoft XDK 3911 CL 13.00.9254.1 with the unchanged natural
|
||||
`/O2 /Oy- /DDEBUG /Dxbox` flags and include graph.
|
||||
|
||||
The hardened comparator proves all 48 padded bytes and zero-relocation
|
||||
identity exact. Target and candidate share normalized SHA-256
|
||||
`d90e91bc9340636a11d9fe06c53bd87fad47428860899fd41c08c65be2cbe273`.
|
||||
The exact-set comparison reports only `_point_from_line2d` as newly exact,
|
||||
preserves all three inherited exact owners, and reports no loss.
|
||||
|
||||
## One-shot discipline and validation
|
||||
|
||||
`git diff --check` and the production compiler's no-output `/Zs` check passed
|
||||
before emission. Exactly one normal selected-object compiler edge produced the
|
||||
retained artifact. No expression, statement order, include topology, flag, or
|
||||
compiler retry occurred.
|
||||
|
||||
The complete graph and campaign gates pass:
|
||||
|
||||
- 377/833 complete objects overall and 275/468 for Halo;
|
||||
- 510,920/2,198,102 meaningful code bytes and 4,237/11,060 functions overall;
|
||||
- 498,006/1,770,166 Halo code bytes and 4,070/7,574 Halo functions;
|
||||
- data unchanged at 1,836,762/4,176,062 overall;
|
||||
- semantic audit: 470 units, 4,349 functions evaluated, 4,203 semantic exact,
|
||||
4,263 accepted exact, and zero unit errors;
|
||||
- admission: zero candidates, contradictions, or revocations;
|
||||
- parks: three active, zero stale, zero invalid;
|
||||
- tooling tests: 179/179 pass, with only the inherited pytest cache-permission
|
||||
warning.
|
||||
|
||||
No protected source, configuration entry, completion label, push, amend, or
|
||||
history rewrite is involved.
|
||||
@@ -1,131 +0,0 @@
|
||||
# `action_vehicle.obj`: opus5 100K consolidated lane (2026-09-14)
|
||||
|
||||
## 1. Scope and provenance
|
||||
|
||||
- Source TU: `source/ai/action_vehicle.c`; target object: `build/split/source/ai/action_vehicle.obj`
|
||||
(January split, SHA-256 `49F00A01...F769` per earlier ledgers).
|
||||
- Compiler: Microsoft XDK 3911 CL 13.00.9254 with the repository's unchanged flags
|
||||
(measured only through `tools/campaign/gate.py`; no ninja/configure run by this worker).
|
||||
- Lane: `opus/100k-consolidated-20260914`, HEAD `b8cd50113`; worker claim `waveA:action_vehicle`.
|
||||
- Evidence used: January COFF (code, relocations, literals); January map atlas
|
||||
`scratch/atlas/action_vehicle.obj.txt`; HCEA `action_vehicle_{desirable,find_destination,setup_specific,setup_impromptu}.c`
|
||||
for semantics only. Prior ledgers read: `action_vehicle_obj_evaluate_seat_symbol_reconciliation_20260913`,
|
||||
`..._fable_control_intake_20260906`, `..._fable_control_reconciliation_20260906`,
|
||||
`..._jonas_distance3d_fixed_point_20260827`, `..._jonas_one_leaf_20260821` and the grep hits in the
|
||||
units/path_obstacles/fable intake ledgers. `branch_sweep.py source/ai/action_vehicle`: no blob with more exact rows.
|
||||
- Per-function worker report (full measurements): `scratch/workers/action_vehicle.md`.
|
||||
|
||||
## 2. Validated baseline
|
||||
|
||||
Gate at lane HEAD: `== exact 10 residual 7 unwritten 0 (of 17 listed)`; no parked entries.
|
||||
|
||||
| Residual | Target padded / relocs / nsha16 | Base padded / relocs | First divergence |
|
||||
| --- | --- | --- | --- |
|
||||
| `_action_vehicle_desirable` | 272 / 7 / e3b1ecf64be4fb82 | 288 / 7 | callee-saved push `edi` vs `esi` (private ABI), dead-test layout |
|
||||
| `_action_vehicle_evaluate_seat` | 976 / 30 / 9f67690555e799a6 | 960 / 31 | `mov eax,[ebp+8]` before actor load; `_vehicle_specific_definition_get` call vs `_tag_get` |
|
||||
| `_action_vehicle_find_destination` | 1232 / 34 / 698d66d07e83af5b | 1264 / 34 | frame `0x464` vs `0x468`; register params `ecx`/`eax` |
|
||||
| `_action_vehicle_perform` | 768 / 18 / e61cabd696765a6f | 768 / 18 | actor/vehicle register swap `edi`/`esi` |
|
||||
| `_action_vehicle_setup_impromptu` | 464 / 18 / 0347ef4f8993dc07 | 464 / 18 | inlined desirable square order; find_destination call ABI |
|
||||
| `_action_vehicle_setup_specific` | 336 / 15 / aa10ba89a138d06b | 336 / 15 | inlined desirable dead test (branchy vs branchless) |
|
||||
| `_distance3d` | 64 / 0 / 4cdb6852c1705b5f | 64 / 0 | x87 square order (exhausted, 2026-08-27) |
|
||||
|
||||
## 3. Accepted controls (retained in production)
|
||||
|
||||
`_action_vehicle_desirable` is strict EXACT (272 padded, 272 meaningful, 7 relocations) in the whole-TU
|
||||
real-file gate `== exact 11 residual 6 unwritten 0`. Two source changes, both in `action_vehicle.c`:
|
||||
|
||||
1. The TU-local `#define REAL_MATH_EXTERNAL_MAGNITUDE_SQUARED3D` / `#undef` pair was removed, which restores
|
||||
the header's default inline linkage. January inlines `magnitude_squared3d` inside the distance test and calls it
|
||||
out of line for the velocity test. With the header default, VC7 makes the same per-call choice by itself.
|
||||
2. The body now reads `boolean desirable = FALSE;` followed by `if (dead) desirable = FALSE; else if (scripted)
|
||||
desirable = TRUE; else { ...; if (already_inside || distance_squared3d(&body, &origin) < max*max) {...} }`.
|
||||
|
||||
Binary support for each part:
|
||||
- January computes the three coordinate differences *after* the `already_inside` test, with no `fstp` cleanup.
|
||||
So the distance is an inline helper in the `||` right operand, not a set of pre-computed locals.
|
||||
- `xor bl,bl` comes before the dead test, which is the initializer.
|
||||
- The not-dead body is placed after the return, which is the if/else-if chain.
|
||||
- January's `setup_specific` inlines desirable with scripted=TRUE as branchless `shr cl,2; not cl; and cl,1`.
|
||||
VC7 only if-converts an if/else whose arms both store constants.
|
||||
- January's `setup_impromptu` inlines desirable, and its dead path jumps to the `xor bl,bl` block that it
|
||||
cross-jumps with the velocity FALSE store. Without an explicit dead-arm store, the dead path jumps straight to the
|
||||
upright test (measured variant s4). So the dead-arm assignment is January's, even though it restates the initializer.
|
||||
|
||||
This match makes no header, config or prototype change. The owner census shows one extra header-inline select-any
|
||||
COMDAT, `_magnitude_squared3d`: January references it undefined, and the same COMDAT is already emitted by many
|
||||
build/base AI objects. There is no data, BSS or COMMON change. The fake scan reports 0 leads.
|
||||
|
||||
## 4. Experiment matrix (all via `gate.py --source`; siblings stayed at 10 exact unless noted)
|
||||
|
||||
| Function | Shape | Size / relocs | Result |
|
||||
| --- | --- | --- | --- |
|
||||
| desirable | v0 named dx/dy/dz (base) | 288 / 7 | residual |
|
||||
| desirable | s3 `distance_squared3d` with external magnitude define | 240 / 8 | out-of-line distance_squared3d |
|
||||
| desirable | s4 s3 without the define | 272 / 7 sha | layout/ABI still off |
|
||||
| desirable | va chain, no init, else-FALSE on distance fail | 272 / 7 sha | reverted |
|
||||
| desirable | **vd** init FALSE + dead-arm FALSE + else-if chain | 272 / 7 | **EXACT, landed** |
|
||||
| desirable | vh va + init | 272 / 7 sha | reverted |
|
||||
| desirable | d1 `magnitude_squared3d(vector_from_points3d())` | sha | desirable lost exact, reverted |
|
||||
| find_destination | f1 MAX / early marker vector / 3D offset cast / chosen.z | 1248 / 34, frame 0x464 | not landed |
|
||||
| find_destination | f2 f1 + `0.35f*0.35f` + bsp local first | 1248 / 34 | not landed |
|
||||
| find_destination | f3 helper args without POINT_FROM_LINE3D define (diagnostic) | guard FAIL (`_point_from_line3d` emitted) | discarded |
|
||||
| find_destination | f4 f2 + scalarised 3D helper vectors | 1232 / 34 sha, frame 0x460, ABI unchanged | not landed |
|
||||
| find_destination | f5 destination operand order | no change | discarded |
|
||||
| evaluate_seat | e0 `#include "units/vehicle_definitions.h"` only | 960 / 31 (reloc name fixed) | not landed alone (no row change) |
|
||||
| evaluate_seat | e1 2D helpers on 3D storage (casts, diagnostic) | 976 / 32 | discarded |
|
||||
| evaluate_seat | e2 e1 + single-exit nesting | 976 / 32 | discarded |
|
||||
| evaluate_seat | e3 e2 + explicit prop-loop distance | 992 / 31 | only site-2 `normalize2d` inlined vs January call |
|
||||
| evaluate_seat | e4/e5/e6/e8/e3ord variants of e3 | 992 / 31 | site-2 still inline |
|
||||
|
||||
## 5. Do-not-repeat list
|
||||
|
||||
- **Measurement trap:** a `sed 's/...\r$//'` on this LF file silently kept the magnitude define, and about 25
|
||||
"inline budget" probes were built against the wrong base. The real per-call inline boundary in desirable was the
|
||||
TU-local define alone. Always `grep -c` the define after generating a variant base.
|
||||
- desirable: named-local distance forms, `magnitude_squared3d(vector_from_points3d())`, the explicit else-FALSE
|
||||
chain, and chain + init + else-FALSE are all measured non-exact.
|
||||
- find_destination: the `_point_from_line3d` inline/out-of-line split cannot be reproduced without emitting the
|
||||
forbidden COMDAT. Destination operand order and bsp-in-arguments are measured inert.
|
||||
- evaluate_seat: none of these changes the site-2 `normalize2d` inline choice: explicit to_seat vector,
|
||||
vector_from_points3d facing, assigned result, conditional context, January function order.
|
||||
- `_distance3d`: see the 2026-08-27 ledger (two waves exhausted).
|
||||
|
||||
## 6. Residual classification
|
||||
|
||||
- **find_destination (policy + ABI).** Measured facts:
|
||||
- January passes `ecx=actor_index, eax=vehicle_index`.
|
||||
- The actor pointer is homed and all body accesses go through one derived pointer.
|
||||
- The destination uses the inline `point_from_line3d` body order, while the refine offset calls `_point_from_line3d`.
|
||||
- The offset vector is a real_vector3d used as perpendicular2d/normalize2d storage.
|
||||
- The approach update is `MAX`, the literal is `0.35f*0.35f`, and the bsp fetch comes first.
|
||||
|
||||
Inferred: the register ABI follows from the body shape, which needs the forbidden COMDAT and a representation cast.
|
||||
- **evaluate_seat (policy + one inline decision).** Measured facts:
|
||||
- The implicit `vehicle_specific_definition_get` call is a missing include.
|
||||
- The body is single-exit.
|
||||
- The facing is a 3D vector normalized as 2D.
|
||||
- The distance is `MIN(distance2d, distance2d)`, and January owns the 2D helper COMDATs.
|
||||
|
||||
Unresolved: VC7 inlines the second `normalize2d` in our build, while January calls it.
|
||||
- **setup_specific, setup_impromptu, perform (ABI/register).** They are blocked by find_destination's private ABI.
|
||||
setup_impromptu also differs in one x87 square order in its inlined desirable copy.
|
||||
- **_distance3d.** x87 scheduling, exhausted.
|
||||
|
||||
## 7. Reopen criteria
|
||||
|
||||
- find_destination: an owner ruling that allows a select-any `_point_from_line3d` COMDAT here, or a C spelling that
|
||||
produces the out-of-line offset call without it; plus admission of the offset-vector storage cast.
|
||||
Start from `scratch/workers/action_vehicle/f/f4.c`.
|
||||
- evaluate_seat: owner admission of the 2D-helper-on-3D-storage casts, plus evidence for the site-2 `normalize2d`
|
||||
inline choice. Start from `scratch/workers/action_vehicle/e/e3.c`, with the `vehicle_definitions.h` include.
|
||||
- setup_specific, setup_impromptu, perform: re-gate as soon as find_destination matches January's ABI.
|
||||
- `_distance3d`: the 2026-08-27 criteria still apply.
|
||||
|
||||
## 8. Disposition
|
||||
|
||||
`action_vehicle.obj` is now 11/17 strict exact (+272 padded bytes: `_action_vehicle_desirable`). It is still active
|
||||
and not Matching. No function is parked or fuzzy-landed by this lane.
|
||||
|
||||
## Orchestrator admission note (checkpoint 1)
|
||||
|
||||
`_action_vehicle_desirable` was **not admitted**. The adversarial verifier rejected the worker's strict-exact form because its dead-vehicle arm re-stores `desirable = FALSE` after the identical initializer, which is a redundant store. The orchestrator also measured the single-assignment form (no initializer, explicit `else desirable = FALSE`): 10 exact / 7 residual, so `desirable` is not exact. `action_vehicle.c` was reverted to HEAD. The `_point_from_line3d` emission and 2D representation-cast proposals are declined under the lane rules.
|
||||
@@ -1,201 +0,0 @@
|
||||
# `action_vehicle.obj`: opus5 150K house-clean lane, wave w1 (2026-09-14)
|
||||
|
||||
## 1. Scope and provenance
|
||||
|
||||
- Source TU: `source/ai/action_vehicle.c`. Target: `build/split/source/ai/action_vehicle.obj` (January split).
|
||||
- Lane `opus/150k-house-clean-20260914`, base `12f7375d4`. Only `source/ai/action_vehicle.c` was modified.
|
||||
No header, config, build, or tool file was touched. No ninja, configure, pytest, or git write was run.
|
||||
- Measurement: `tools/campaign/gate.py`, `alndiff`, `relocdiff`, `tinfo`, `scratch/parkcheck.py`, and `tools/fake_match_scan.py`.
|
||||
A `/Zs /W3` warning census was also run with the unit's own cflags.
|
||||
- Ledgers read: all 11 `action_vehicle_obj_*` logs, including `opus5_100k_20260914` and its admission note, plus the
|
||||
`opus5_100k_consolidated_HANDOFF_20260914` rejections. The 100K worker report is at
|
||||
`C:\halo-worktrees\opus5-100k-consolidated-20260914\scratch\workers\action_vehicle.md`.
|
||||
- `git log --all` shows 14 commits for the file. `branch_sweep`: the best historical blob has 9 exact functions.
|
||||
- Evidence sources:
|
||||
- January COFF: code, relocations, and COMDAT set.
|
||||
- HCEA `action_vehicle_{desirable,evaluate_seat,find_destination}.c`: semantics and topology only.
|
||||
- January `actors.obj` `.rdata` assert literals (section 5).
|
||||
- Per-function worker report: `scratch/workers/action_vehicle.md`. Candidates are in `scratch/workers/action_vehicle/`.
|
||||
|
||||
## 2. Baseline (real file at lane base, guard on)
|
||||
|
||||
`== exact 10 residual 7 unwritten 0 (of 17 listed)`. The unit has no parks.
|
||||
|
||||
| Residual | Target padded / relocs | Base tags |
|
||||
| --- | --- | --- |
|
||||
| `_action_vehicle_desirable` | 272 / 7 | size 288 |
|
||||
| `_action_vehicle_evaluate_seat` | 976 / 30 | size 960, relocs 31 |
|
||||
| `_action_vehicle_find_destination` | 1232 / 34 | size 1264 |
|
||||
| `_action_vehicle_perform` | 768 / 18 | sha |
|
||||
| `_action_vehicle_setup_impromptu` | 464 / 18 | sha |
|
||||
| `_action_vehicle_setup_specific` | 336 / 15 | sha |
|
||||
| `_distance3d` | 64 / 0 | sha |
|
||||
|
||||
## 3. Landed (final real-file gate `== exact 12 residual 5`, guard passed)
|
||||
|
||||
| Function | Padded | Meaningful | Relocs | Normalized sha16 |
|
||||
| --- | ---: | ---: | ---: | --- |
|
||||
| `_action_vehicle_perform` | 768 | 767 | 18 | e61cabd696765a6f |
|
||||
| `_action_vehicle_setup_specific` | 336 | 328 | 15 | aa10ba89a138d06b |
|
||||
|
||||
The gain is **1,104 padded / 1,095 meaningful** code bytes. All 10 baseline-exact rows are unchanged. The row diff is:
|
||||
- perform and setup_specific: residual -> EXACT;
|
||||
- find_destination: tag 1264 -> 1248.
|
||||
|
||||
### 3.1 New lever: callee register pressure through a late-bound position pointer (find_destination)
|
||||
|
||||
January `action_vehicle_find_destination` is a private register-ABI function. Every caller loads
|
||||
`ecx = actor_index` and `eax = vehicle_index`, then pops 0x18.
|
||||
|
||||
**How January's body uses the actor pointer.** The actor datum pointer is stored once at entry, to `[ebp-0x14]`.
|
||||
It is loaded exactly once, at +0x113, immediately after the anchor-point selection, into `edi`:
|
||||
|
||||
mov edi,[ebp-0x14]; fsub [edi+0x12c]; add edi,0x12c; ...
|
||||
|
||||
All later body-position reads go through that one pointer, including the `debug->field_C8` struct copy
|
||||
(`mov edx,edi`). In the base source the actor pointer was used at every site, so it took `ebx`, and
|
||||
`vehicle_index` lost its register parameter.
|
||||
|
||||
**Source change.** `real_point3d const *actor_position;` is declared with the block locals. It is assigned
|
||||
`&actor->input.position.body_position` immediately before its first use, which is the entry-direction computation after
|
||||
the anchor selection. Every body-position read goes through it.
|
||||
|
||||
**Why the assignment point matters (measured):**
|
||||
|
||||
| Placement of the pointer | Result |
|
||||
| --- | --- |
|
||||
| Initialized at the top of the if-block (f2) | ABI unchanged |
|
||||
| Initialized at the top of the function (f5) | ABI unchanged |
|
||||
| Assigned just before the anchor selection (f8) | ABI unchanged |
|
||||
| Assigned just after the anchor selection (f3 / landed m1) | January ABI |
|
||||
| Declared and initialized in a nested block after the anchor selection (f4) | January ABI (not used, because it needs a bare block) |
|
||||
|
||||
With the pointer assigned after the anchor selection, the pointer's live range begins where January's `edi` derivation begins.
|
||||
Only the minimal routing change was landed. The residual rule does not allow more changes to this function.
|
||||
find_destination stays residual at 1248/34 with frame 0x468 (January 0x464). Its first 0x55 bytes are now identical to January.
|
||||
|
||||
### 3.2 Non-redundant desirable chain (required prerequisite)
|
||||
|
||||
The landed desirable has no initializer. It reads:
|
||||
|
||||
if (dead) desirable = FALSE;
|
||||
else if (scripted) desirable = TRUE;
|
||||
else { ...; desirable = FALSE; if (already_inside || distance_squared3d(body, origin) < max*max) { desirable = TRUE; if (moving) desirable = FALSE; } }
|
||||
|
||||
The upright veto follows unchanged. The TU-local `REAL_MATH_EXTERNAL_MAGNITUDE_SQUARED3D` define/undef pair is removed, as the 100K lane
|
||||
proved necessary. Semantics are identical to the base on all inputs, and no store restates an earlier value. This avoids the
|
||||
redundant dead-arm re-store that got the 100K `vd` form rejected.
|
||||
|
||||
This body gives desirable January's private ABI (`eax = actor_index`, `esi = vehicle_index`) and January's branch layout.
|
||||
- **perform:** the new ABI removes perform's actor/vehicle register swap.
|
||||
- **setup_specific:** its inline copy gets January's branchless dead/scripted if-conversion.
|
||||
|
||||
Measured prerequisites:
|
||||
|
||||
| Variant | Result |
|
||||
| --- | --- |
|
||||
| Base desirable + m1 | perform, setup_specific residual |
|
||||
| d1 keeping the magnitude define | perform grows to 880 bytes |
|
||||
| d3 (d1 with named dx/dy/dz) | setup_specific exact, perform not |
|
||||
| d2 (boolean-expression form) | desirable no longer inlined into setup_impromptu |
|
||||
|
||||
desirable itself stays residual at 288/7. The only remaining difference is that the not-scripted `desirable = FALSE` store is not hoisted
|
||||
into January's entry `xor bl,bl`.
|
||||
|
||||
### 3.3 Checks
|
||||
|
||||
- Point guard passed.
|
||||
- parkcheck: no parks.
|
||||
- Owner census against `build/base`: one added select-any COMDAT, `_magnitude_squared3d`. January references it undefined from desirable
|
||||
and setup_impromptu; it is the systemic header-inline class. There is no data, BSS, or COMMON change, and nothing is dropped.
|
||||
- Fake scan: 0 leads (base 0).
|
||||
- `/W3` warnings: identical to the base.
|
||||
|
||||
## 4. Not landed
|
||||
|
||||
| Function | Final | Classification / reason |
|
||||
| --- | --- | --- |
|
||||
| `_action_vehicle_evaluate_seat` | 960/31 in the real file; **strict EXACT scratch candidate** `E1.c` | Blocked only by the earlier orchestrator decline of 2D-helper casts; see section 5 |
|
||||
| `_action_vehicle_find_destination` | 1248/34 | Offset-vector representation cast, plus x87 operand-order ties (below) |
|
||||
| `_action_vehicle_desirable` | 288/7 | Owner ruling on the vd dead-arm restatement |
|
||||
| `_action_vehicle_setup_impromptu` | 464/18 sha | Depends on vd. With vd + m1 only the inlined x,z,y square order differs |
|
||||
| `_distance3d` | 64 sha | Exhausted per the 2026-08-27 ledger |
|
||||
|
||||
**find_destination cast diagnostic (x2/x5).** Size 1232, frame 0x464, and January's success/failure epilogue layout are reached with a
|
||||
single-exit `found` flag. The remaining x87 operand-order differences were measured inert:
|
||||
- destination `fld down.i; fmul t`: operand swap, `test.x + down.i*t`, and the inline point_from_line3d body (diagnostic, guard failure)
|
||||
all still load `t` first;
|
||||
- the refine dot operand order;
|
||||
- the offset_distance temp lifetime;
|
||||
- the chosen-to-actor square order.
|
||||
|
||||
**distance3d via a genuine caller (g1).** Using the header-inline copy through `distance3d(&marker, hint_point)` emits the header body with
|
||||
sha 01d7809ae796fc6e, which is the wave-one z,x,y schedule. That is a measured negative: the COMDAT body does not depend on its callers.
|
||||
|
||||
## 5. evaluate_seat: new levers and the proposal
|
||||
|
||||
The 100K lane stopped at 992/31: its cast form still inlined the second `normalize2d`. Three new measured VC7 levers close
|
||||
that gap. All three are cast-independent mechanisms.
|
||||
|
||||
1. **Loop spelling controls post-loop inline frequency.**
|
||||
- `for (prop = next; prop; prop = next)` keeps `normalize2d(&to_seat_direction)` inline.
|
||||
- `while (prop = prop_iterator_next(&iterator))`, or `prop = next; while (prop) {...; prop = next;}`, makes it an out-of-line call
|
||||
as in January.
|
||||
- A diagnostic with the loop deleted also puts the call out of line. The rotated for-loop inflates the estimated frequency of the code
|
||||
after it.
|
||||
2. **Sibling scope shares a frame slot.** Putting the 8-byte `prop_iterator` in its own block around the loop lets it share `[ebp-0x18]`
|
||||
with `to_seat_direction`. The frame goes from 0x5c to 0x54.
|
||||
3. **Single exit (HCEA topology).** The body sets `result = TRUE` after the entrance point is found. A conflicting actor does
|
||||
`result = FALSE; break;`. The tail sits in `if (result)` with one `return result;`. This reproduces January's three epilogues:
|
||||
the threaded `xor al,al`, the tail-duplicated `mov al,1`, and `mov al,bl`.
|
||||
|
||||
The candidate `scratch/workers/action_vehicle/E1.c` (the current real file plus `E1.txt`) makes evaluate_seat **strict EXACT at 976/30/9f67690555e799a6**.
|
||||
- Whole-TU gate: exact 13, with all 12 real-file exact rows kept.
|
||||
- Point guard passed; fake scan 0 leads.
|
||||
- Census: adds a header-inline `_dot_product2d` COMDAT (systemic class).
|
||||
- It also adds the legal `#include "units/vehicle_definitions.h"`. This removes the base's C4013 implicit
|
||||
`vehicle_specific_definition_get` call to a nonexistent `_vehicle_specific_definition_get`.
|
||||
|
||||
**Casts in the candidate:**
|
||||
- `normalize2d((real_vector2d *)&facing)`;
|
||||
- `MIN(distance2d((real_point2d *)&body, (real_point2d *)&entrance_point), distance2d(... &seat_point))`;
|
||||
- `vector_from_points2d((real_point2d *)&body, (real_point2d *)&seat_point, &to_seat_direction)`;
|
||||
- `dot_product2d(&to_seat_direction, (real_vector2d *)&actor->input.facing_vector)`.
|
||||
|
||||
**New January-side evidence for these casts:**
|
||||
- January `actors.obj` `.rdata` contains the assert literals `(real_vector2d *) &actor->input.facing_vector` and
|
||||
`(real_vector2d *) &control_data.facing_vector`. These are stringified by `assert_valid_real_normal2d`, and canonical
|
||||
`source/ai/actors.c:1946-1950` and `4167-4171` already reproduce them. So Bungie's AI code applied 2D helpers to 3D vectors through
|
||||
exactly this cast.
|
||||
- The canonical tree already carries 31 such casts in admitted exact code. Examples:
|
||||
- `action_obey.c:2449` `normalize2d((real_vector2d *)&facing) == 0.0f`;
|
||||
- `action_obey.c:2615-2622`;
|
||||
- `action_charge.c:769/834`;
|
||||
- `actor_combat.c:2310`;
|
||||
- `actor_firing_position.c:1548`.
|
||||
- January's own action_vehicle COMDAT set is `point_from_line2d`, `distance_squared2d`, `distance2d`, `negate_vector2d`, `distance3d`,
|
||||
in `real_math.h` order. It shows that this TU instantiated the 2D helpers.
|
||||
|
||||
**ORCHESTRATOR-PROPOSAL:** admit these January-attested casts for `action_vehicle_evaluate_seat`, and apply `E1.txt` (the function body plus the
|
||||
include) to `source/ai/action_vehicle.c`. Expected gain: 976 padded bytes. No header or config change; the change has no external consumers.
|
||||
|
||||
## 6. Do-not-repeat (this wave)
|
||||
|
||||
- desirable:
|
||||
- d1/d2/va/d3 and d1 with the magnitude define (all measured above);
|
||||
- the dead-arm restatement (vd) is the only exact form.
|
||||
- find_destination pointer placement: f2, f5 and f8 do not change the ABI. Accessor binding on the first use only (f1) does not change it either.
|
||||
- The destination x87 load order is inert to operand order, sum order, and the inline point_from_line3d body.
|
||||
- setup_impromptu: d2 stops the desirable inline.
|
||||
- `_distance3d`: the header copy via a genuine caller gives the z,x,y body.
|
||||
- evaluate_seat, still inline: nested `normalize2d(vector_from_points2d(...))` (e4), splitting the first condition into nested ifs (e5),
|
||||
and a no-op cast on the site-2 argument (ed1).
|
||||
|
||||
## 7. Reopen criteria
|
||||
|
||||
- **evaluate_seat:** the cast ruling in section 5 (candidate ready).
|
||||
- **find_destination:** the cast ruling, plus a source spelling that controls the destination/refine x87 operand order. Start from
|
||||
`scratch/workers/action_vehicle/x5.c`. The closer cast-free body is `f7.c`.
|
||||
- **desirable, setup_impromptu:** an owner ruling on vd, or a non-redundant source whose FALSE store VC7 hoists to the entry.
|
||||
After that, the inlined x,z,y square order in setup_impromptu remains.
|
||||
- **`_distance3d`:** the 2026-08-27 criteria.
|
||||
@@ -1,166 +0,0 @@
|
||||
# action_vehicle.obj - opus5 250K house-clean lane, wave w3d (2026-09-15)
|
||||
|
||||
Unit: `source/ai/action_vehicle.c`. Worker notes: `scratch/workers/w3d_action_vehicle.md`.
|
||||
Scratch: `scratch/workers/w3d_action_vehicle/`. Predecessors: the 11 earlier
|
||||
`action_vehicle_obj_*` ledgers, in particular `_obj_opus5_100k_20260914.md` and `_obj_opus5_150k_w1_20260914.md`.
|
||||
|
||||
## Baseline and result
|
||||
|
||||
| | exact | residual | unwritten |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| HEAD (baseline, guard on) | 12 | 5 | 0 |
|
||||
| after w3d | 13 | 4 | 0 |
|
||||
|
||||
Newly strict EXACT: `_action_vehicle_evaluate_seat` - 976 padded bytes, 30 relocations, sha 9f67690555e799a6.
|
||||
No parks for this unit; no baseline-exact row changed; `_point_from_line3d` emitted-symbol guard passed.
|
||||
|
||||
Remaining non-exact rows: `_action_vehicle_desirable` 272 [size 288, sha], `_action_vehicle_find_destination`
|
||||
1232 [size 1248, sha], `_action_vehicle_setup_impromptu` 464 [sha], `_distance3d` 64 [sha].
|
||||
|
||||
## 1. What unblocked the object
|
||||
|
||||
`scratch/w3/laws_w3.md` section B lists, under "Newly ADMITTED by verifiers (do not avoid)":
|
||||
"(real_point2d const *)&point3d casts into 2D helpers (32 source sites, HCEA); A15 role order for distance2d",
|
||||
landed in wave w3a as `_actor_move_avoidance_setup` (see `actor_moving_obj_opus5_150k_w3_20260914.md` line 77).
|
||||
Wave w1 had already produced a strict-EXACT `_action_vehicle_evaluate_seat` body and withheld it for exactly that
|
||||
policy. The 2026-09-15 owner rulings (brief sections 9b/9c) do not touch the cast class, so no new ruling was needed.
|
||||
|
||||
## 2. `_action_vehicle_evaluate_seat` - EXACT, landed
|
||||
|
||||
Target 976 / 30 / 9f67690555e799a6; HEAD was 960 / 31 / sha.
|
||||
|
||||
Structural census before the work:
|
||||
- One relocation too many (31 vs 30). January calls `_normalize2d` twice (@0x00c1 for the entry facing, @0x0283
|
||||
for the to-seat direction) and `_tag_get` twice; ours inlined the second normalize2d and emitted an extra
|
||||
`_tag_get` produced by the C4013 implicit declaration of `vehicle_specific_definition_get` at line 471
|
||||
(`scratch/gate4/c4013.txt`).
|
||||
- 16 bytes short (960 vs 976) from the same two effects plus the frame.
|
||||
|
||||
The landed body combines five measured levers:
|
||||
1. **A7 missing prototype.** `#include "units/vehicle_definitions.h"` - the genuine owner, which defines
|
||||
`vehicle_specific_definition_get` as a macro over `tag_get` at vehicle_definitions.h:30. No consumer-local
|
||||
prototype (R8). This also removes the paired C4047 "differs in levels of indirection" warning.
|
||||
2. **Admitted 2D-helper casts.** `normalize2d((real_vector2d *)&facing)`,
|
||||
`distance2d((real_point2d const *)&actor->input.position.body_position, (real_point2d const *)&entrance_point)`,
|
||||
the MIN of that and the seat distance, `vector_from_points2d(... , &to_seat_direction)` and
|
||||
`dot_product2d(&to_seat_direction, (real_vector2d const *)&actor->input.facing_vector)`. `const` is used wherever
|
||||
the real_math.h parameter is `const`, matching the admitted w3a idiom.
|
||||
3. **A23-class loop spelling.** `while (prop = prop_iterator_next(&iterator))`. A rotated
|
||||
`for (prop = next; prop; prop = next)` inflates the estimated frequency of the code after the loop and inlines
|
||||
the second `normalize2d`; the while form leaves it out of line exactly like January. The idiom is already in the
|
||||
tree at actions.c:4454, action_obey.c:1826 and actor_looking.c:734.
|
||||
4. **Sibling scope.** The prop iterator and `prop` live in their own block around the loop, so VC7 shares their
|
||||
8-byte slot with `to_seat_direction` ([ebp-0x18]) and the frame drops 0x5c -> 0x54.
|
||||
5. **A3/A29 single exit.** `result = TRUE` after the entrance-point success, `result = FALSE; break;` for the
|
||||
conflicting actor, the whole publish tail under `if (result)`, one `return result;`. This reproduces January's
|
||||
three epilogues: the break threads to `xor al,al`, the success path tail-duplicates `mov al,1`, the failures
|
||||
share `mov al,bl`.
|
||||
6. **A17 discarded validation call.** The `if (!allow_any_seat)` block is the bare statement
|
||||
`vehicle_specific_definition_get(vehicle->definition_index);` followed by
|
||||
`unit_seat_is_driver(vehicle_index, seat_index);`. The earlier candidate used an unused local plus a `(void)`
|
||||
cast, which A17 rejects.
|
||||
|
||||
Shapes: E1 (the w1 body, re-gated at this HEAD) EXACT; v1 = E1 plus the const casts and the A17 bare statement,
|
||||
EXACT - landed.
|
||||
|
||||
Checks: all 12 baseline-EXACT rows preserved (row-by-row `--all` diff); guard passed; `scratch/parkcheck.py` reports
|
||||
no parks for the unit; owner census versus `build/base` adds only `_dot_product2d`, a real_math.h select-any
|
||||
header-inline COMDAT of the class laws_w2 A4 accepts as systemic (`_vector_from_points3d`, `_magnitude_squared3d`,
|
||||
`_normalize2d`, `_square_root`, `_scale_vector2d`, `_vector_from_points2d`, `_magnitude2d`, `_magnitude_squared2d`,
|
||||
`_distance_squared3d` are already candidate-only owners at HEAD, so R14 is not newly triggered); no data, BSS or
|
||||
COMMON change; `tools/fake_match_scan.py` 0 leads (HEAD 0); `CL /Zs /W3` removes C4013 and C4047 and adds nothing.
|
||||
|
||||
Authenticity: the routine computes the seat entry facing from entrance to seat in the XY plane, falls back to the
|
||||
actor own facing vector when that degenerates, takes the nearer of the entrance and seat 2D distances, rejects the
|
||||
seat when a friendly actor is already closer to the same seat, and publishes weight / range / facing / fake flags
|
||||
only for an accepted seat. Every helper used is the real_math.h routine the arithmetic is named after.
|
||||
|
||||
## 3. `_action_vehicle_find_destination` - structural gap closed in scratch, not landed
|
||||
|
||||
Target 1232 / 34 / 698d66d07e83af5b; HEAD 1248 / 34, frame 0x468 against the January 0x464.
|
||||
|
||||
Census (recorded before any shape):
|
||||
- **Relocation census by target**: 34 versus 34, every symbol count equal, with ONE real difference -
|
||||
January references `__real@3dfae147` where we emit `__real@3dfae148`. `0x3dfae147` is `(float)(0.35f*0.35f)`,
|
||||
the square of the float 0.35f; `0x3dfae148` is the decimal literal `0.1225f`. The HEAD source writes the folded
|
||||
literal; January wrote the product. This is an emitted-constant fidelity defect, not a tie.
|
||||
- **Relocation ORDER**: January calls `_global_collision_bsp_get` at @0x40f, BEFORE the `_global_up3d` read at
|
||||
@0x418; ours calls it at @0x47e just before `_collision_bsp_test_vector`. By the store/call-order law the BSP
|
||||
pointer is obtained before the test_point and down_vector statements, i.e. it is a block-top declaration
|
||||
`struct collision_bsp *collision_bsp = global_collision_bsp_get();`, not an inline argument.
|
||||
- **Frame census** (`slots.py` over `alndiff --include-equal`): January `sub esp,0x464`, ours `sub esp,0x468`.
|
||||
Ours owns one extra dword `[ebp-0x50]` (3 references, all in the trailing collision block) which pushes the
|
||||
collision result buffer from `[ebp-0x464]` to `[ebp-0x468]`. January packs BOTH trailing aggregates into slots
|
||||
the earlier block already owns (test_point -> [ebp-0x10..-8], down_vector -> [ebp-0x24..-0x1c]); ours packs only
|
||||
down_vector. laws_w2 A6 side law: nested-block locals may pack.
|
||||
- **Statement order from the aligned stream**: January computes `marker.x - actor_position->x` and
|
||||
`marker.y - actor_position->y` at @0x116/@0x130, i.e. in the OUTER block before `anchor_point` is assigned, and
|
||||
reuses those two cells in the `t` numerator and the perpendicular sign test - a named outer-block 2D vector is
|
||||
missing from HEAD. The tail is single-exit (`test al,al; je <fail>` with the success block inline, `mov al,1`
|
||||
and a separate `xor al,al` epilogue). `*surface_index_reference` is stored FIRST, its load interleaved into the
|
||||
x destination product.
|
||||
|
||||
All five defects are implemented by the w1 diagnostic body `x5.c`, which the cast admission now makes usable. On
|
||||
top of it this wave spent five evidence-led shapes:
|
||||
|
||||
| shape | change | result |
|
||||
| --- | --- | --- |
|
||||
| s1 | the two hand-written 2D sign dots become `dot_product2d(...)` calls (A35(1)+(2)) | 411 vs 412 insns; also closed the point_from_line2d x87 CSE pop and the magnitude_squared3d k,j,i sum order. KEPT |
|
||||
| s2 | `collision.t*down_vector.i + test_point.x` (t-first) | byte identical, inert. REVERTED |
|
||||
| s3 | `scale_vector3d(global_down3d, 4.0f, &down_vector);` for the three component multiplies (A35(1) leaf age) | 412 vs 412 instructions at IDENTICAL addresses; closed the stray `fxch st(1)` and the Y/Z destination products. KEPT |
|
||||
| s4 | surface_index store moved after the destination stores | worse. REVERTED |
|
||||
| s5 | dot-2 argument swap | byte identical - confirms laws_w3 A44. REVERTED |
|
||||
|
||||
Fixed point `scratch/workers/w3d_action_vehicle/fd_cand.c` (the current real file with only find_destination
|
||||
replaced): 1232 / 34, `[sha]` only - the `[size]` tag is gone - 412/412 instructions at identical addresses,
|
||||
whole-TU `== exact 13 residual 4`, guard passed, fakescan 0 leads, no new warnings, owner census +`_dot_product2d`
|
||||
and +`_scale_vector3d` (both A30/A4 accepted class) and the `.rdata` literal corrected to `__real@3dfae147`.
|
||||
|
||||
Eleven instructions remain, in four x87 leaf-age / scheduling families: the i-term of the first inlined
|
||||
`dot_product2d` (@0x284), both terms of the second (@0x36e, @0x377), the interleave of the
|
||||
`debug->field_F8 = chosen_point` loads against the `debug->field_F4 = TRUE` byte store (@0x3dd), and the X
|
||||
destination product (@0x483/@0x48c; Y and Z now match).
|
||||
|
||||
NOT LANDED under brief section 6: an already-written residual may be landed only when it becomes strict EXACT, and
|
||||
this candidate is not below the January size or relocation count, so the fuzzy allowance does not apply.
|
||||
|
||||
Reopen criterion: a source lever that flips x87 leaf age inside an inlined `dot_product2d` or a named-local product
|
||||
without an R3 operand swap (A35 is diagnostic only today); or an orchestrator decision to take the strictly-closer
|
||||
zero-credit body for its proven fidelity content - notably the emitted constant, where HEAD writes `0.1225f`
|
||||
(`__real@3dfae148`) and January writes `0.35f*0.35f` (`__real@3dfae147`).
|
||||
|
||||
## 4. `_action_vehicle_desirable` - initializer proven, blocked by the pending A42 ruling
|
||||
|
||||
Target 272 / 7 / e3b1ecf64be4fb82; HEAD 288 / 7 (100 versus 112 instructions).
|
||||
|
||||
Census: relocations 7/7 with identical targets; frame slots identical apart from one extra `[ebp-8]` read. The
|
||||
16-byte gap is therefore not a frame gap: it is our two extra reloads of the datum homed at `[ebp-8]` plus the
|
||||
position of `xor bl,bl`.
|
||||
|
||||
New evidence this wave: laws_w3 A38/A42 fire. January zeroes BL at 0x2b, before the `test al,4` dead-bit compare at
|
||||
0x2d, which A42 reads as proof of a declaration initializer. Shape `d4` - `boolean desirable = FALSE;` at the
|
||||
declaration plus `if (!TEST_FLAG(vehicle->object.damage_flags, _object_dead_bit)) { if (scripted_request) ... else
|
||||
... }`, with no redundant store anywhere - reproduces that hoisted `xor bl,bl` exactly and brings the row to
|
||||
**272 bytes, the January size**, at 101 versus 100 instructions. So the initializer, not the w1 `vd` redundant
|
||||
dead-arm store, is what the January entry proves.
|
||||
|
||||
Two families still differ in `d4`, and they are coupled:
|
||||
- January keeps `vehicle_index` in its incoming ESI and the vehicle datum in EDI (pushing only ebx and edi);
|
||||
`d4` moves `vehicle_index` into EDI and the vehicle datum into ESI, which flips the private ABI of the static.
|
||||
`_action_vehicle_perform` (768) and `_action_vehicle_setup_specific` (336), both exact at HEAD, then fall back to
|
||||
`[sha]` (`== exact 11 residual 6`). Losing an exact row is a regression, so `d4` is not landable.
|
||||
- January lays the not-dead block out of line (`je 0x58`, `jmp 0x31` back); the `d4` `if (!dead) { ... }` body stays
|
||||
inline. HEAD's `if (dead) X; else if ... else ...` chain reproduces the January layout, but its first arm cannot
|
||||
be empty, so the only spelling carrying BOTH the initializer and the chain is the w1 `vd` redundant store.
|
||||
|
||||
Reopen criterion: the pending A42 owner ruling on byte-proven redundant stores (laws_w3 C3 groups
|
||||
`_encounter_test_rule`, `_extract_sequence`, `_action_alert_next_position` and `_action_obey_command_begin` here).
|
||||
If granted, `vd` plus this wave's initializer evidence closes desirable at 272, and the w1 ledger records that
|
||||
`_action_vehicle_setup_impromptu` then has only the inlined x,z,y square order left.
|
||||
|
||||
## 5. Not targets this wave
|
||||
|
||||
`_action_vehicle_setup_impromptu` (464, [sha]) and `_distance3d` (64, [sha]) were not in the w3d TARGET list and no
|
||||
shapes were spent. w1 classified setup_impromptu as desirable-dependent (it inlines desirable) plus one x87
|
||||
square-order tie, and `_distance3d` as exhausted - a caller-independent header COMDAT body whose two frozen waves
|
||||
and the w1 `g1` rename-removal probe all produce z,x,y or z,y,x against the January x,y,z.
|
||||
@@ -1,295 +0,0 @@
|
||||
# `actions.obj` exact-match log
|
||||
|
||||
## Scope and standard
|
||||
|
||||
This lane reconstructs `source/ai/actions.obj` from the January 14, 2002 Xbox
|
||||
object. The HCEX decompilation and Fable correspondence packets are source
|
||||
topology hints only. January code bytes, relocation identities, data bytes,
|
||||
and symbol ownership decide every result. The lane uses the established XDK
|
||||
3911 compiler and unchanged `/O2 /Oy- /DDEBUG /Dxbox` flags. Assembly,
|
||||
volatile, inline-control keywords, optimizer barriers, undefined behavior,
|
||||
byte forcing, flag changes, and comparator exceptions are out of scope.
|
||||
|
||||
## Fresh baseline (`fc8e1b07`)
|
||||
|
||||
The target contains 63 functions and 19,172 meaningful padded code bytes.
|
||||
The fresh candidate has zero exact functions: 62 functions are absent and
|
||||
`actor_action_debug_color` is 160 bytes with 15 relocations versus January's
|
||||
176 bytes and 15 relocations. January also owns the 888-byte/96-relocation
|
||||
`global_action_functions` constant block and the 16-byte/3-relocation
|
||||
`global_actor_mode_names` data block; neither is emitted by the baseline.
|
||||
|
||||
Fable's exact-unique name map covers 55 of the 63 functions (17,484 January
|
||||
bytes), and the local HCEX tree has readable C for those names. That coverage
|
||||
does not grant match credit. It only gives this lane a much better starting
|
||||
shape than decompiling every body from raw instructions.
|
||||
|
||||
## Strategy
|
||||
|
||||
The first wave is deliberately small: callback dispatchers, names, class and
|
||||
default-state accessors, plus the existing debug-color function. These are
|
||||
the low-risk functions that establish the action table's exact layout and
|
||||
common dispatcher shapes. Header-inline helpers are not duplicated in this
|
||||
translation unit; they should be emitted naturally once real callers require
|
||||
them. The entire object is rebuilt and compared after every coherent wave so
|
||||
an apparent local win cannot hide a sibling or ownership regression.
|
||||
|
||||
## Experiments
|
||||
|
||||
### Wave 1, natural HCEX/January topology
|
||||
|
||||
The six dispatcher bodies were written as ordinary callback-table lookups with
|
||||
the January action-index assertion restored at its original file and line.
|
||||
The two name getters and default-state getter use a single initialized result
|
||||
and one range guard. `actor_action_debug_color` retained the existing body and
|
||||
restored the missing signed lower-bound check. The first compile made nine of
|
||||
the eleven functions exact. The only two misses were otherwise-identical
|
||||
conditional branches: `jae` in the candidate versus January's `jge` in
|
||||
`actor_mode_name` and `actor_action_get_default_state`.
|
||||
|
||||
That difference came from using `NUMBEROF(array)`, whose unsigned result
|
||||
converted the short index before the upper-bound comparison. Replacing the
|
||||
two unsigned counts with named enum constants kept the code readable and
|
||||
restored the original signed comparison. The second compile made all eleven
|
||||
functions exact. `_global_actor_mode_names` also matches as a 16-byte data
|
||||
owner with the exact three string relocations and null final entry.
|
||||
|
||||
Strict result after Wave 1: **11/63 functions**, **1,088/19,172 code bytes**,
|
||||
and **16/16 bytes of the actor-mode-name data owner** are exact. No existing
|
||||
exact function regressed and no shared header was changed.
|
||||
|
||||
### Waves 2-4, panic and berserk leaves
|
||||
|
||||
The next twelve leaf functions were recovered from the exact-unique HCEX map,
|
||||
then checked individually against January. The HCEX bodies supplied names and
|
||||
high-level intent, while January supplied the missing Xbox-only details. Two
|
||||
general source-shape findings mattered:
|
||||
|
||||
* The redundant sign extension in the attached-melee panic handler comes from
|
||||
applying the ordinary `MAX` macro directly to a short field and an enum. An
|
||||
explicitly typed temporary removes that promotion and does not match.
|
||||
* January has a local-game debug bypass in the panic-from-damage threshold
|
||||
which is absent from HCEX. Naming byte +8 in `ai_debug_state` recovered the
|
||||
condition without changing that structure's layout. January only applies
|
||||
the bypass to a local connection; spelling the connection test in the other
|
||||
direction leaves one branch different.
|
||||
|
||||
The projectile and burning handlers also proved the responsible-unit and
|
||||
active-prop call chains. January's relocation identities, not just the call
|
||||
count, were used to distinguish those helpers. At the end of these waves the
|
||||
object was **23/63 functions exact, 2,688/19,172 code bytes**; all earlier
|
||||
matches remained exact.
|
||||
|
||||
### Wave 5, action stopping and transition denial
|
||||
|
||||
`actor_action_can_stop_guarding` first compiled to the correct logic but used
|
||||
four-byte integer result materialization. Casting the two comparison
|
||||
expressions to the real one-byte `boolean` type produced January's `setge al`,
|
||||
`xor al,al`, and shared one-byte true exit exactly. This is a type recovery,
|
||||
not a code-forcing cast: the API genuinely returns the project's byte-sized
|
||||
boolean.
|
||||
|
||||
`actor_action_deny_transition` initially nested `encounter_get` inside
|
||||
`encounter_get_squad`. That changed argument evaluation and cleanup order.
|
||||
Binding the encounter datum first, as a readable named local, reproduced
|
||||
January's call order and naturally emitted the 144-byte
|
||||
`encounter_get_squad` header helper. Spelling the timer branch as
|
||||
`combat_status >= 5` followed by expiration (with denial in the `else`) fixed
|
||||
the remaining branch direction. Both functions and the helper are strict
|
||||
exact.
|
||||
|
||||
For `actor_action_can_stop_conversing`, an initialized `TRUE` result preserves
|
||||
the no-conversation exit. A compound logical expression and three explicit
|
||||
early returns both placed the shared true block at the end. The readable
|
||||
`if/else if/else` result chain places the first true block where January does
|
||||
and makes later true branches jump backward to it. The result is strict exact,
|
||||
including the scenario tag-block access and all six relocation destinations.
|
||||
|
||||
Strict result after Wave 5: **27/63 functions**, **3,280/19,172 code bytes**,
|
||||
plus the exact actor-mode-name data owner. No exact sibling regressed.
|
||||
|
||||
### `actor_action_allow_cover_seeking` live residual
|
||||
|
||||
The semantic body is recovered and January proves that the damage comparison
|
||||
uses `recent_body_damage` (+0x1c0), despite the HCEX reconstruction naming it
|
||||
as shield damage. Direct definition-field accesses recover January's x87
|
||||
loads and avoid a spurious float local. Four declaration/scope variants for
|
||||
the short visibility duration and the long-lived `allow` boolean have been
|
||||
measured. They preserve 8/8 relocation destinations but our current source
|
||||
keeps the duration in `BX` and spills `allow`; January keeps `allow` in `BL`
|
||||
and reuses the dead second-parameter home for the duration. Declaration order
|
||||
alone did not move this allocation. The readable best body remains in source
|
||||
as a nonexact reconstruction; no credit is granted, and register-forcing or
|
||||
volatile tricks are barred.
|
||||
|
||||
### Waves 6-7, setup leaves and transition handlers
|
||||
|
||||
`actor_action_try_to_seek_cover` and `actor_action_try_to_panic` use a complete
|
||||
`action_state_data` union, not a member-sized scratch buffer. The full union
|
||||
is part of the original readable contract even though each setup helper only
|
||||
writes its own member; it also reproduces January's stack frame and argument
|
||||
layout. `actor_action_handle_pending_command_list` likewise needed the full
|
||||
union and the original ordering: perform the immediate action first, then
|
||||
clear the command-list reference. All three compiled strict-exact on the
|
||||
first measured natural shape.
|
||||
|
||||
`actor_action_handle_done_fleeing`, `actor_action_handle_combat_failure`, and
|
||||
`actor_action_handle_berserk_transition` were recovered from the mapped source
|
||||
and January control flow. The fleeing handler retains the original `success`
|
||||
assert and source line 2681. `actor_action_handle_combat_transition` also has
|
||||
an Xbox-only tail absent from HCEX: when already in combat with status zero it
|
||||
calls `actor_action_class` and deliberately discards the value. That call is
|
||||
not dead trivia--it preserves the original range assertion. These four
|
||||
handlers are all strict-exact.
|
||||
|
||||
`actor_action_handle_exit_pursuit` exposed a useful source-shape rule. Assigning
|
||||
each action's done flag directly to the return variable made VC7 reuse `AL` for
|
||||
the flag tests instead of January's `DL`. Calling lost-contact directly from
|
||||
each successful case fixed the registers but allowed the compiler to combine
|
||||
the preceding cdecl cleanup in the wait arm. The exact readable topology is:
|
||||
test each action flag directly, set a one-byte `reported = TRUE` marker after
|
||||
any perception notification, then make one common lost-contact call when the
|
||||
marker is set. This preserves separate cleanup, keeps flag tests in `DL`, and
|
||||
leaves the called result naturally in `AL`.
|
||||
|
||||
Strict result after Wave 7: **33/63 functions**, **4,208/19,172 code bytes**,
|
||||
plus the exact actor-mode-name data owner. Every previously exact sibling
|
||||
remained exact.
|
||||
|
||||
### `actor_action_handle_grenade_throwing` live residual
|
||||
|
||||
The January semantics and all seven relocation destinations are recovered.
|
||||
Readiness requires a target type of at least five and rejects a fleeing actor
|
||||
whose panic type is positive; the variant definition is fetched before those
|
||||
checks. The two grenade-stimulus cases use combat status or the prop's swarm
|
||||
state, and an already-armed throw is attempted after consideration. The best
|
||||
readable body is 224 bytes versus January's 208. January keeps the result in
|
||||
`BL`, reloads the actor index for calls, and emits a sign-extended short switch;
|
||||
the current compiler keeps the actor index in `EBX`, spills the result byte,
|
||||
and retains word comparisons. Moving the result and short declarations did
|
||||
not change that allocation. The function remains nonexact and uncredited;
|
||||
broader semantic work continues before any tie classification.
|
||||
|
||||
### Wave 8, vehicle and grenade leaves
|
||||
|
||||
`actor_action_try_to_enter_vehicle` initially gave VC7 a separate working
|
||||
pointer for either the caller's seat list or the local fallback array. That
|
||||
extra lifetime changed the January register assignment. Reusing the optional
|
||||
parameter itself as the working pointer is both ordinary C and the natural
|
||||
contract: when the pointer is null it is assigned the local array, otherwise
|
||||
the caller-supplied count is used. Keeping the loop count short and sharing
|
||||
the final false return then reproduced all 208 bytes and six relocations.
|
||||
|
||||
`actor_action_try_to_throw_grenade` required four semantic details that the
|
||||
later HCEX body obscured. The damage rejection is spelled `!(damage > 0)` so
|
||||
the original NaN path is preserved; the normalized direction must be positive;
|
||||
the facing rejection is `!(dot < cosine)`; and the throw order sets the combat
|
||||
flag before clearing the pending-plan flag. The minimum cosine is named from
|
||||
its January float bits rather than replaced by a decimal approximation. The
|
||||
result is strict-exact at 288 bytes and twelve relocations.
|
||||
|
||||
The neighboring `actor_action_consider_grenade` is reconstructed and has the
|
||||
exact 288-byte size and all eleven relocations. Its remaining bytes are only
|
||||
three references to one stack slot: January colors the base-chance temporary
|
||||
at `[ebp-4]`, while this build colors it at `[ebp-8]`. Tested shapes include a
|
||||
single combined expression, three named float temporaries, moving those
|
||||
declarations outside the check, moving them before the last-check local, and
|
||||
scoping the last-check local inside a nested block. The best readable shape
|
||||
retains the named base/difficulty/result calculation and is not credited.
|
||||
|
||||
### Wave 9, exact vehicle-exit cluster
|
||||
|
||||
The mapped HCEX vehicle-exit topology incorrectly returned immediately when
|
||||
the actor had no vehicle. January always clears `stimuli.vehicle_eviction`,
|
||||
including that path, so the search is a guarded body followed by unconditional
|
||||
cleanup. The first corrected shape reached exact size and relocation count,
|
||||
but kept the successful `exited` value live in `BL` across `game_time_get`.
|
||||
January calls `game_time_get`, stores the re-entry deadline, and only then sets
|
||||
`exited = TRUE`. That source statement order lets VC7 return constant `AL=1`
|
||||
on the successful path while retaining the false result slot for both failure
|
||||
paths. The complete handler is strict-exact at 336 bytes and seven
|
||||
relocations.
|
||||
|
||||
The adjacent private `code_0000b140` is the vehicle re-entry cooldown check.
|
||||
It takes the actor index in the compiler-selected `EAX` private convention and
|
||||
the vehicle index on the stack, returning false only while the requested
|
||||
vehicle equals `vehicle_ignore_index` and the deadline is still in the future.
|
||||
The direct readable predicate compiled strict-exact on its first build: 64
|
||||
bytes and three relocations.
|
||||
|
||||
### `actor_action_handle_vehicle_entry` checkpoint residual
|
||||
|
||||
The full 960-byte January behavior is reconstructed, including both candidate
|
||||
sources: friendly player-driven vehicle props and the 32-entry scripted
|
||||
enterable-vehicle registry. The source-local registry layout is proven as
|
||||
0x28 bytes per entry at `ai_globals+0x3B8`; no shared AI header was expanded.
|
||||
The helper calls, object types, distances, team/type masks, packed AI-index
|
||||
matching, and action setup give the exact 22 relocation destinations.
|
||||
|
||||
The first natural form was 960 bytes but mirrored the long-lived actor pointer
|
||||
and actor index between `EBX` and `EDI`. Making the result a real named
|
||||
success/failure value restored January's register roles. Further measured
|
||||
changes were semantic rather than register forcing:
|
||||
|
||||
* spell the best-distance test as `!(distance < best)` to reject NaNs exactly;
|
||||
* compare the packed encounter component through a dword xor plus `& 0xFFFF`,
|
||||
rather than letting VC7 narrow the xor to a word;
|
||||
* express AI scope selection as a switch, producing January's decrement chain;
|
||||
* increment the long loop variables normally while comparing their short
|
||||
views, avoiding extra sign extension; and
|
||||
* assign the prop-derived squared distance before its vehicle index, allowing
|
||||
the independent integer store to fill the x87 multiply window.
|
||||
|
||||
Those changes make the body instruction-identical over its substantive search
|
||||
windows. The best checkpoint form is 944 bytes with all 22 relocations and
|
||||
differs in the false-return topology: January materializes a zero byte in
|
||||
`DL` for the three early guards and retains a separate late false epilogue;
|
||||
this compiler folds both blocks despite equivalent named-result and explicit
|
||||
label spellings. No barrier, volatile, register forcing, or control-flow byte
|
||||
trick was attempted. The readable body stays as a nonexact reconstruction
|
||||
and receives no credit.
|
||||
|
||||
## Checkpoint status before canonical reconciliation
|
||||
|
||||
The independent wave ends at **37/63 strict-exact functions** and
|
||||
**4,760/19,172 meaningful January code bytes (24.83%)**. Those functions
|
||||
occupy 5,104 padded section bytes; keeping the meaningful and padded measures
|
||||
separate avoids overstating progress. The 16-byte/3-relocation
|
||||
actor-mode-name data owner is also strict-exact. The 888-byte action dispatch
|
||||
table remains deliberately disabled because callbacks in other unfinished
|
||||
action translation units are not yet linkable; it receives no data credit.
|
||||
The only shared-header changes are prototypes in `actions.h` and a
|
||||
layout-neutral name for the already-existing byte at `ai_debug_state+8`.
|
||||
`actors.h`, `ai.h`, `ai_communication.h`, `encounters.h`, `path.h`, and the
|
||||
other headers concurrently used by the AI-debug lane were not modified.
|
||||
|
||||
## Canonical reconciliation and final checkpoint gates
|
||||
|
||||
The checkpoint was rebased onto canonical `a0bad121` before final validation.
|
||||
The Actions object was then forcibly deleted and rebuilt with the unchanged
|
||||
January campaign flags. The hardened semantic audit still finds exactly
|
||||
37 strict functions (4,760 meaningful bytes), while direct `coff_compare`
|
||||
confirms `_global_actor_mode_names` at 16 bytes, three relocations, and
|
||||
normalized SHA-256
|
||||
`374708fff7719dd5979ec875d56cd2286f6d3cf7ec317a3b25632aab28ec37bb`.
|
||||
The object remains `NonMatching`; no function, data, semantic, or parked
|
||||
exception was added to configuration.
|
||||
|
||||
The fail-closed regression gate took a fresh Actions snapshot, deleted and
|
||||
rebuilt the object again, and reported all 37 functions `still_exact`, with
|
||||
zero changed nonexact functions, newly exact warnings, failures, ownership
|
||||
warnings, or other warnings. Full `halobetacache_build` and `libcmt_build`
|
||||
both passed after the rebase, so the layout-neutral header name and Actions
|
||||
prototypes compile across every consumer. `progress` and `semantic_progress`
|
||||
completed with 470 units scanned, 3,473 semantic-exact functions, 93 hidden
|
||||
exact functions, and zero unit errors. The admission audit produced no new
|
||||
completion candidate; this checkpoint intentionally receives no object-level
|
||||
credit.
|
||||
|
||||
All **179/179** tool tests passed. `git diff --check` is clean, the config
|
||||
diff is empty, and the added production code contains no assembly, volatile,
|
||||
force/no-inline annotation, optimizer barrier, undefined-behavior trick,
|
||||
byte forcing, compiler-flag change, or comparator change. Original behavior
|
||||
that may look surprising is retained and explained above rather than silently
|
||||
"fixed". This is therefore an honest readable-C foundation checkpoint, not
|
||||
a claim that `actions.obj` is finished.
|
||||
@@ -1,182 +0,0 @@
|
||||
# `actions.obj` Codex closure ledger
|
||||
|
||||
This file continues the Actions investigation without modifying the earlier
|
||||
Claude-authored `actions_obj.md`. January's object is always authoritative;
|
||||
HCEX/PDB material is used only to recover names, types, and plausible source
|
||||
topology. Every experiment below changes one readable-C factor, rebuilds the
|
||||
whole translation unit, and receives no credit unless the hardened comparator
|
||||
accepts the complete function and its relocation identities.
|
||||
|
||||
## Verified starting point
|
||||
|
||||
After a fresh rebuild, 55 of 63 functions are strict exact. Both owned data
|
||||
sections are also exact: the combined 888-byte/96-relocation action table block
|
||||
and the 16-byte/3-relocation actor-mode-name block. The eight remaining
|
||||
functions have the correct target section size and relocation count:
|
||||
|
||||
- `code_0000b3b0`
|
||||
- `actor_action_handle_vehicle_entry`
|
||||
- `actor_action_handle_combat_selection`
|
||||
- `actor_action_handle_lost_contact`
|
||||
- `actor_action_try_to_dive`
|
||||
- `actors_searching_same_position`
|
||||
- `actor_action_handle_evasion`
|
||||
- `actor_action_handle_danger_avoidance`
|
||||
|
||||
The reconstructed `actor_action_handle_surprise` must retain
|
||||
`boolean result = FALSE;`. Removing the initializer loses an explicit January
|
||||
zero materialization and regresses that previously exact function.
|
||||
|
||||
## Rejected closure experiments
|
||||
|
||||
### Vehicle entry: enclosing negative guard
|
||||
|
||||
The target has three result epilogues, so the setup tail was respelled as an
|
||||
enclosing negative guard in an attempt to separate its late false exit from
|
||||
the early named-result exit. The function stayed 960 bytes with 22
|
||||
relocations, but the allocator and control-flow graph changed broadly: 240
|
||||
normalized byte positions differed instead of the prior best 39 and several
|
||||
call relocations moved. The prior readable best form was restored.
|
||||
|
||||
### Lost contact: HCEX local declaration order
|
||||
|
||||
The nested scalar declarations were reordered to match the later HCEX
|
||||
CodeView record. This did not recover January's private helper convention or
|
||||
frame coloring. `actor_action_handle_lost_contact` still had about 1,204
|
||||
different positions, while `code_0000b3b0` stayed at 327; multiple relocation
|
||||
sites shifted. The January-best declaration order was restored.
|
||||
|
||||
### Evasion: mixed direct and named-result exits
|
||||
|
||||
The return topology was rewritten to mirror the apparent January split between
|
||||
direct success exits and named-result exits. VC7 instead cross-jumped the
|
||||
blocks, shrinking the function from 800 to 784 bytes and worsening the overlap
|
||||
to 513 differing positions with downstream relocation shifts. The prior
|
||||
800-byte/27-relocation form was restored.
|
||||
|
||||
### Try to dive: authentic vector aggregate by itself
|
||||
|
||||
HCEX CodeView names a `real_vector2d evade_vector`, so the two scalar alignment
|
||||
components were replaced with that aggregate without altering expressions or
|
||||
control flow. Under external linkage this was codegen-neutral in the relevant
|
||||
allocation: the function remained 720 bytes/29 relocations with 634 differing
|
||||
positions and broad relocation-offset drift. The proven scalar form was
|
||||
restored.
|
||||
|
||||
### Try to dive: static linkage by itself
|
||||
|
||||
HCEX CodeView says the original function was file-local. Making only the
|
||||
definition `static` recovered January's important entry allocation exactly:
|
||||
`actor_index` stayed in ESI and was copied to EDI for debug-array indexing.
|
||||
However, the candidate then emitted only 704 bytes, retained 29 relocations,
|
||||
and differed at 493 normalized positions. Its first remaining mismatch was
|
||||
the actor spill at `[ebp-0x20]` rather than January's `[ebp-0x18]`; the switch
|
||||
also merged two cases that January keeps separate. Static linkage was
|
||||
therefore reverted. This is useful diagnostic evidence, not a match claim.
|
||||
|
||||
The target's external COFF symbol versus a static candidate is not by itself a
|
||||
permanent blocker: this same object already has strict-exact file-local
|
||||
functions whose csplit target symbol is external. The static experiment is
|
||||
rejected because its bytes and section size miss, not merely because the COFF
|
||||
storage-class numbers differ.
|
||||
|
||||
### Try to dive: scalar declaration order
|
||||
|
||||
This experiment retained external linkage and changed declaration order only.
|
||||
January's stack homes are: best animation at `-0x8`, best score at
|
||||
`-0xC`, best direction at `-0x10`, actor spill at `-0x18`, and the alignment
|
||||
components at `-0x1C/-0x20`. The best candidate previously put the alignment
|
||||
components first at `-0x8/-0xC`, pushing the later values downward. Therefore
|
||||
the alignment declarations were moved after the three best-choice scalars.
|
||||
A fresh whole-object build was byte-identical to the prior external baseline:
|
||||
720 bytes, 29 relocations, normalized SHA beginning `e669dd20`, first mismatch
|
||||
at `+0x0D`, and 634 differing overlap positions. The entry still destructively
|
||||
used EDI and the actor spill remained at `-0x20`. VC7's coloring is invariant
|
||||
to this declaration ordering, so the readable original order was restored.
|
||||
|
||||
### Combat selection: scalar declaration order
|
||||
|
||||
January places the cached prop distance at `[ebp-0x8]`, the melee charge delay
|
||||
at `[ebp-0xC]`, and the actor-variant definition pointer at `[ebp-0x10]`.
|
||||
The candidate instead cycles those values through `-0xC`, `-0x10`, and
|
||||
`-0x8`. To test whether this was ordinary declaration coloring,
|
||||
`prop_distance` and `charge_delay` were declared before the variant pointer;
|
||||
the `REAL_MAX` assignment and every call remained at their previous execution
|
||||
points. The rebuilt 1,776-byte/56-relocation function was unchanged in the
|
||||
relevant allocation: the variant pointer remained at `-0x8`, prop distance at
|
||||
`-0xC`, first mismatch at `+0x41`, and 1,013 normalized positions differed.
|
||||
Later relocation sites also retained the broad allocation cascade. The
|
||||
original readable declaration order was restored; simple declaration order is
|
||||
not a control for this three-value cycle.
|
||||
|
||||
### Combat selection: direct last-attempt field
|
||||
|
||||
January keeps the current game time in EDI and does not load
|
||||
`last_melee_check_time` until the comparison, while the candidate's named
|
||||
`last_attempt_time` local caused that field to be hoisted into EDI. Removing
|
||||
the local and spelling the two adjacent comparison reads directly from the
|
||||
actor tested whether the field binding caused the register cascade. Instead,
|
||||
VC7 shrank the function from 1,776 to 1,760 bytes, kept 56 relocations, moved
|
||||
the first mismatch to `+0x6A`, and increased the overlap difference to about
|
||||
1,200 positions. The desired local register change did not preserve the
|
||||
surrounding control-flow/allocation topology. The named readable local was
|
||||
restored.
|
||||
|
||||
## Frozen 55/63 checkpoint
|
||||
|
||||
The last rejected experiment was fully restored and a fresh build again
|
||||
reports **55 of 63 functions strict exact**. This is the checkpoint source,
|
||||
not a claim that `actions.obj` is complete. Each of the eight remaining
|
||||
functions still has January's exact padded section size and relocation count;
|
||||
their normalized bytes and/or symbolic relocation placement remain different,
|
||||
so none receives credit. The combined 888-byte action-table/default-state
|
||||
owner remains exact at 96 relocations, and the 16-byte actor-mode-name owner
|
||||
remains exact at three relocations.
|
||||
|
||||
The bounded closing experiments above now answer the natural source questions
|
||||
they were designed to test. In particular, simple declaration reordering did
|
||||
not control the residual stack coloring, direct-field spelling caused a broad
|
||||
allocation cascade, and topology rewrites changed section size or cross-jump
|
||||
behavior. No independently supported readable-C factor remains ready for a
|
||||
production experiment. Freezing the verified source is therefore safer than
|
||||
turning register-allocation symptoms into speculative source churn.
|
||||
|
||||
The object intentionally stays `NonMatching`: `config.json`, the parked
|
||||
ledger, compiler flags, comparator, and semantic-credit files are unchanged.
|
||||
No assembly, volatile access, force/no-inline annotation, optimizer barrier,
|
||||
undefined-behavior trick, type-punning byte force, or compiler-flag change was
|
||||
used. January quirks are retained, including the original
|
||||
`code_0000c970` assertion that does not validate
|
||||
`escape_is_ledge_reference`. The separate Claude-authored
|
||||
`actions_obj.md` was not edited, renamed, or deleted; this Codex-owned file is
|
||||
the only new object log.
|
||||
|
||||
## Final checkpoint gates
|
||||
|
||||
The restored source was rebuilt again with the unchanged campaign compiler and
|
||||
flags before the checkpoint audit. `research/actions_strict_status.py`
|
||||
returned 55/63, and the hardened semantic report independently recorded those
|
||||
same 55 functions at **10,906 of 19,172 meaningful January code bytes
|
||||
(56.89%)** and 11,392 padded bytes. The eight residual rows above retain
|
||||
their exact January padded sizes and relocation counts. Direct hardened COFF
|
||||
comparison also reconfirmed both data owners: the 888-byte/96-relocation
|
||||
combined block has normalized SHA-256
|
||||
`b4bd37bc3750a724b625c0254a2b8bc3272c1aff70c71ae46952bac6acd4a9ab`,
|
||||
and the 16-byte/3-relocation name block has normalized SHA-256
|
||||
`374708fff7719dd5979ec875d56cd2286f6d3cf7ec317a3b25632aab28ec37bb`.
|
||||
|
||||
The full Halo and libcmt build targets pass. Fresh progress and semantic
|
||||
generation scanned 470 units with zero unit errors; the admission audit found
|
||||
no Actions completion candidate and granted no credit. All 179 tool tests
|
||||
pass. `git diff --check`, the config/parked/semantic-credit diff, the
|
||||
forbidden-construct scan, and the Claude-Markdown preservation audit are
|
||||
clean.
|
||||
|
||||
The formal regression-manifest snapshot is the sole administrative gate not
|
||||
recorded in this worktree. It correctly refuses to snapshot a dirty tree, and
|
||||
the desktop Git metadata ACL/approval-service usage limit prevented creation
|
||||
of the local checkpoint commit needed to make the tree clean. The forced
|
||||
Actions rebuild and strict whole-object sweep itself did pass at 55/63; the
|
||||
lane is left commit-ready so the clean-commit snapshot/check can be run as
|
||||
soon as Git metadata writes are available. This limitation does not turn the
|
||||
checkpoint into object-level credit.
|
||||
@@ -1,144 +0,0 @@
|
||||
# Actions large natural-C pair and no-fake audit (2026-08-30)
|
||||
|
||||
## Scope
|
||||
|
||||
This wave starts from canonical commit
|
||||
`fa102b086bebdf6f874145025a05323c8f9d9d3f` and changes only the large
|
||||
`source/ai/actions` reconstruction plus the headers that own its shared enums
|
||||
and prototypes. The pre-wave Actions gate was 55/63 strict-exact functions.
|
||||
|
||||
The source frontier came from the Fable history rather than a wholesale
|
||||
cherry-pick:
|
||||
|
||||
- commit `79275995c484a2637aa5db570030d42a9e02685d`, source blob
|
||||
`d8d32fb630fb70e6bc8733efd97fcd69b31c397f`, supplied the combat-selection
|
||||
and first evasion candidates;
|
||||
- commit `c8ff585ee941bd8454e991d7512b5b36ba0f161a`, source blob
|
||||
`92eb33aa4cd3e94a2dda31edf6bf9063faf59de1`, supplied the danger-avoidance
|
||||
experiment;
|
||||
- the later house-rule commit
|
||||
`2a9ede1cc37821492fe56ddbecb5898f60073605`, source blob
|
||||
`bc1ceba344612a50a191e36f2fda1d8d47d0242f`, is controlling evidence for
|
||||
the no-fake review below.
|
||||
|
||||
No donor commit was transplanted wholesale.
|
||||
|
||||
## Accepted strict functions
|
||||
|
||||
`_actor_action_handle_combat_selection` is strict-exact:
|
||||
|
||||
- 1,776 padded bytes;
|
||||
- 56 relocations with identical addresses, types, and destinations;
|
||||
- normalized SHA-256
|
||||
`2fb7b29eea215e53086b6ce6fd971c3eb4ed361fa45f1c836d3e4833c2edf5ed`.
|
||||
|
||||
The unusual calls were reviewed rather than accepted merely because they
|
||||
match. The independent target lift at
|
||||
`research-cache/stian-halo-current-20260827/src/halo/ai/actions.c` lines
|
||||
2461-2713 proves the controlled-unit type-verification call and the discarded
|
||||
`actor_has_ranged_weapon` call before melee charge setup. Both calls therefore
|
||||
express original behavior, including their validation/side effects; neither is
|
||||
an inert compiler lever. The same lift corroborates the vehicle cooldown and
|
||||
lookup order, charge-state policy, and final assertion ladder. Negated real
|
||||
comparisons retain the January x87 unordered/NaN behavior and are not Boolean
|
||||
noise.
|
||||
|
||||
`_actor_action_handle_evasion` is strict-exact:
|
||||
|
||||
- 800 padded bytes;
|
||||
- 27 relocations with identical addresses, types, and destinations;
|
||||
- normalized SHA-256
|
||||
`f38b2a0650790ee8d848ca0a4faee7a8cee3c00e2ad3048412b62c8db594370b`.
|
||||
|
||||
The admitted source is ordinary structured C: the first successful cover or
|
||||
panic action sets `result`, and the remaining policy is guarded by
|
||||
`if (!result)`. The perceived-danger branch is positive, later successes only
|
||||
set `result`, and the function has one terminal return. There is no donor
|
||||
`goto`, label, assembly, volatile state, wrapper, optimizer directive, object
|
||||
patch, or undefined behavior. Direct-return, compound-guard, and nested
|
||||
single-exit forms were measured; the nested single-exit form is both natural
|
||||
and uniquely strict. `boolean result;` followed by `result = FALSE;` is kept as
|
||||
an evidence-backed exception to the declaration/assignment preference: a
|
||||
same-line initializer changed 657 bytes and the relocation schedule.
|
||||
|
||||
The accepted gain is therefore two functions and 2,576 padded code bytes:
|
||||
55/63 to 57/63.
|
||||
|
||||
## Honest rejection of a coincidental exact result
|
||||
|
||||
`_actor_action_handle_danger_avoidance` is deliberately **not** accepted.
|
||||
The donor's only strict form changed the ordinary condition
|
||||
|
||||
```c
|
||||
if (!body_within_danger)
|
||||
```
|
||||
|
||||
into an empty positive arm followed by the real work in `else`. Fable commit
|
||||
`2a9ede1cc` independently identifies that shape as an exact-only fake-match
|
||||
generator and reverts it. This wave keeps the coherent negative condition.
|
||||
The result is honestly residual at 1,504 candidate bytes versus the 1,520-byte
|
||||
January function, with 34 relocations on both sides and candidate normalized
|
||||
SHA-256
|
||||
`b1d5ecaf33b392f8b6071a515b226a8c41e112097105096e0216f9554e3b328f`.
|
||||
No credit, exception, adjudication, or park is added for it.
|
||||
|
||||
## Private helper and inline ownership
|
||||
|
||||
The private `_code_0000c970` placeholder is renamed
|
||||
`actor_action_find_escape_from_danger` and remains `static`. HCEA PDB/cross-
|
||||
build correspondence and the January-addressed function atlas both provide
|
||||
that original name; this is not an address-derived invention.
|
||||
|
||||
An initial exact experiment manually reproduced the formal parameter aliases
|
||||
of `point_from_line3d`. It was rejected under the no-fake rule because those
|
||||
aliases conveyed no policy and existed only to control compiler scheduling.
|
||||
Production instead uses six plain coordinate assignments, an established
|
||||
project idiom. This ordinary form remains strict-exact at 928 bytes, 28
|
||||
relocations, and normalized SHA-256
|
||||
`ec0b698df2d40432b1b2a912ebc33eca0a989f2420cc69d3b184ab8131a34e11`.
|
||||
The rebuilt object owns no symbol containing `point_from_line3d`, preserving
|
||||
the January inline/COMDAT boundary without fake source.
|
||||
|
||||
## Type, enum, and prototype ownership
|
||||
|
||||
- `destination_type`, `actor_vehicle_driver_type`, and the danger-zone enums
|
||||
live in `actors.h`, their closest shared owner.
|
||||
- `action_class` lives in `actions.h`.
|
||||
- the complete communication type/hostility enums and
|
||||
`ai_communication_event` declaration live in `ai_communication.h`.
|
||||
- local numeric switch/action/hostility values were replaced with the matching
|
||||
enum constants.
|
||||
- the duplicate local danger enum in `actor_perception.c` and duplicate local
|
||||
communication prototype in `actions.c` were removed.
|
||||
- all real-valued locals use `real`; typed object access uses the appropriate
|
||||
`unit_get`/`vehicle_get` paths.
|
||||
|
||||
## Verification
|
||||
|
||||
The final rebuilt Actions gate reports 57 exact, six residual, and zero
|
||||
unwritten functions. The six residuals are the honest danger-avoidance form
|
||||
plus the five inherited residuals:
|
||||
|
||||
- `_actor_action_handle_lost_contact`;
|
||||
- `_actor_action_handle_vehicle_entry`;
|
||||
- `_actor_action_try_to_dive`;
|
||||
- `_actors_searching_same_position`;
|
||||
- `_code_0000b3b0`.
|
||||
|
||||
The full `halobetacache_build` and `libcmt_build` targets pass. Consolidated
|
||||
`progress` and `semantic_progress` pass with 470 units scanned, 4,986 functions
|
||||
evaluated, 4,876 semantic-exact functions, 131 hidden exact functions, 4,886
|
||||
accepted exact functions, and zero unit errors. All 212 tool tests pass.
|
||||
`tools.parked_functions` reports 13 active, zero stale, and zero invalid
|
||||
entries. `git diff --check` is clean.
|
||||
|
||||
Claude's prototype fake-smell scanner reports no smell in `actions.c`. Its
|
||||
three reports are pre-existing empty-then forms in `actor_perception.c`, outside
|
||||
this Actions admission and unchanged by this wave. They receive no new credit.
|
||||
|
||||
The old pre-wave regression manifest is not used to waive failures: moving
|
||||
enums/prototypes to their owning headers and applying the supported private
|
||||
symbol rename intentionally changes compiler-private/debug ownership. Strict
|
||||
function comparison proves exactly two accepted gains and no loss among the 55
|
||||
pre-wave exact functions. A clean committed-state Actions snapshot and forced
|
||||
rebuild/check are captured after this ledger is committed.
|
||||
@@ -1,116 +0,0 @@
|
||||
# `actions.obj` policy-reconciled replay (2026-08-27)
|
||||
|
||||
## Result
|
||||
|
||||
The preserved Actions reconstruction was replayed into the integration tree and
|
||||
reconciled with the newer shared headers and house rules.
|
||||
|
||||
- strict functions: **0/63 -> 55/63**
|
||||
- strict padded function bytes: **0 -> 11,392**
|
||||
- unwritten owners: **62 -> 0**
|
||||
- residual owners: **1 -> 8**
|
||||
- `_global_action_functions`: **888 bytes / 96 relocations, exact**
|
||||
- normalized SHA-256:
|
||||
`b4bd37bc3750a724b625c0254a2b8bc3272c1aff70c71ae46952bac6acd4a9ab`
|
||||
- `_global_actor_mode_names`: **16 bytes / 3 relocations, exact**
|
||||
- normalized SHA-256:
|
||||
`374708fff7719dd5979ec875d56cd2286f6d3cf7ec317a3b25632aab28ec37bb`
|
||||
|
||||
The strict project board after a forced 569-object rebuild is:
|
||||
|
||||
```text
|
||||
objects 270/619
|
||||
functions 4445/8246
|
||||
bytes 592087/1922669
|
||||
```
|
||||
|
||||
The forced rebuild exposed eight additional exact `units.obj` functions from
|
||||
already-committed Units source. Those 5,808 bytes are not credited to this
|
||||
Actions replay. Actions itself contributes 55 functions and 11,392 bytes.
|
||||
|
||||
## Provenance read before integration
|
||||
|
||||
- donor tree:
|
||||
`C:\Users\isabe\Documents\Codex\2026-07-13\i-w\work\actions-full-20260813`
|
||||
- preserved Claude ledger:
|
||||
`docs/object_matching_logs/actions_obj.md`
|
||||
- preserved Codex closure ledger:
|
||||
`docs/object_matching_logs/actions_obj_codex_closure.md`
|
||||
- historical integration precedent:
|
||||
`66112c6181b2e882e3382e739aaeb528606d4285`
|
||||
- house rules source:
|
||||
`C:\Users\isabe\Documents\Codex\2026-07-13\i-w\units-complete-20260824\docs\house_rules.md`
|
||||
- house rules SHA-256:
|
||||
`9294B81DC2E1C92D75FFD2F9F289287131BDBA3564BA95BB054B08189781BFE1`
|
||||
|
||||
The two preserved ledgers remain verbatim. This file records only the
|
||||
integration-specific reconciliation and verification.
|
||||
|
||||
## Policy and header reconciliation
|
||||
|
||||
The donor's raw byte-offset accessors and private cast overlays were not copied
|
||||
into production. They were replaced with typed source constructs whose layouts
|
||||
are compile-time pinned:
|
||||
|
||||
- `prop_datum` reads use the canonical `enemy` and `dead` members at `+0x60`
|
||||
and `+0x127`.
|
||||
- `actor_datum` movement reads use `control.moving` at `+0x504`.
|
||||
- the donor's `unit_definition + 0x238` access was identified as
|
||||
`unit.dive_distance`, not `unit.evade_distance`; the nested offset sum is
|
||||
asserted as `0x238`.
|
||||
- the two vehicle AI values use a TU-local completion of the already-declared
|
||||
`struct vehicle_definition`, returned directly by the typed
|
||||
`vehicle_specific_definition_get` macro. Their offsets are pinned at
|
||||
`0x390` and `0x394`.
|
||||
- debug writes use the canonical `struct actor_debug_info`. The mapped cover,
|
||||
grenade, danger, and dive clusters are pinned at `0xB8`, `0x150`, `0x168`,
|
||||
and `0x184`; the complete record is pinned at `0x657C`.
|
||||
- the image-attested `ai_debug.flee_always` byte at `+0x8` replaces the donor's
|
||||
incompatible private view without changing `struct ai_debug_state` size.
|
||||
- the Actions view of `ai_globals` pins `grenades_enabled` at `0x3B4`, the
|
||||
enterable-vehicle array at `0x3B8`, and the complete local prefix at `0x8B8`.
|
||||
|
||||
The newer Units lane intentionally declares the animation-impulse argument as
|
||||
`long`. Keeping the reconstructed evade animation local as `long` preserves
|
||||
January's full-register call shape and the exact 464-byte
|
||||
`actor_action_try_to_evade` owner without changing Claude's active Units header.
|
||||
|
||||
All reconstructed declarations use one parameter per line, every no-argument
|
||||
list places `void` on its own line, and every reconstructed `void` definition
|
||||
has an explicit terminal `return;`.
|
||||
|
||||
## Strict residual frontier
|
||||
|
||||
```text
|
||||
1776 actor_action_handle_combat_selection
|
||||
1520 actor_action_handle_danger_avoidance
|
||||
800 actor_action_handle_evasion
|
||||
1872 actor_action_handle_lost_contact
|
||||
960 actor_action_handle_vehicle_entry
|
||||
720 actor_action_try_to_dive (candidate 704)
|
||||
320 actors_searching_same_position
|
||||
368 code_0000b3b0
|
||||
```
|
||||
|
||||
No residual is credited. The preserved donor ledger contains the exhaustive
|
||||
negative matrices and the best measured shapes for these eight owners.
|
||||
|
||||
## Verification
|
||||
|
||||
```text
|
||||
build\local-tools\ninja.exe -t clean all_source
|
||||
build\local-tools\ninja.exe all_source
|
||||
python -B tools/campaign/verdicts.py scratch/actions_replay_after.json
|
||||
python -B tools/campaign/verdicts.py --diff \
|
||||
scratch/actions_replay_before.json scratch/actions_replay_after.json
|
||||
python -B tools/campaign/gate.py source/ai/actions
|
||||
python -B tools/campaign/gate.py source/ai/ai_debug
|
||||
python -B tools/campaign/gate.py source/ai/ai
|
||||
python -B tools/campaign/gate.py source/units/units
|
||||
python -B tools/campaign/board.py
|
||||
```
|
||||
|
||||
The before/after verdict diff reports **63 gains and 0 regressions**. Actions
|
||||
gates at **55 exact / 8 residual / 0 unwritten**. `ai.obj` remains 13 exact
|
||||
with no residual owners, `ai_debug.obj` retains all 11 prior exact owners, and
|
||||
`units.obj` gates at its committed **183 exact / 6 residual / 0 unwritten**.
|
||||
@@ -1,20 +0,0 @@
|
||||
# `actions.obj` pursuit-helper name recovery (2026-08-31)
|
||||
|
||||
The January symbol atlas and HCEA release PDB recover the private helper at
|
||||
file offset `0xB3B0` as `actor_action_determine_pursuit_options`, with static
|
||||
linkage. The source, caller, symbol atlas comment, and `config/symbols.json`
|
||||
now use that name instead of `code_0000b3b0`.
|
||||
|
||||
Claude's experimental removal of the `controlled_by_group` formal was not
|
||||
retained. The later PDB authenticates the complete interface, and deleting a
|
||||
real parameter merely changed the private register convention. The parameter
|
||||
and its call argument remain. The artificial explanatory `(void)` use was
|
||||
removed because it had no semantic or machine-code role and claimed more
|
||||
January provenance than the evidence supports.
|
||||
|
||||
This is a naming/authenticity correction, not byte-match credit. The helper
|
||||
remains an honest 368-byte, six-relocation residual (98.24428% objdiff), and
|
||||
`actions.obj` remains 57 exact / 6 residual / 0 unwritten. The existing
|
||||
Actions closure ledgers already record the bounded source experiments; no
|
||||
register-forcing construct, ABI lie, or speculative parameter deletion is
|
||||
introduced here.
|
||||
@@ -1,83 +0,0 @@
|
||||
# `actions.obj` large fuzzy closeout (2026-09-01)
|
||||
|
||||
## Result
|
||||
|
||||
The canonical `source/ai/actions` reconstruction remains the strongest known
|
||||
source frontier: **58/63 strict-exact functions, five residual functions, and
|
||||
zero unwritten functions**. No production C changed in this pass. All five
|
||||
remaining bodies are now evidence-backed fuzzy parks under the current house
|
||||
rule, so future exact work requires genuinely new provenance or a natural
|
||||
same-compiler code-generation lever.
|
||||
|
||||
The five honest residuals account for 5,392 January padded bytes:
|
||||
|
||||
| Function | Target | Candidate | Relocations | Fuzzy |
|
||||
| --- | ---: | ---: | ---: | ---: |
|
||||
| `_actor_action_handle_vehicle_entry` | 960 | 960 | 22 / 22 | 96.54422% |
|
||||
| `_actor_action_handle_lost_contact` | 1,872 | 1,872 | 55 / 55 | 95.328384% |
|
||||
| `_actor_action_handle_danger_avoidance` | 1,520 | 1,504 | 34 / 34 | 90.41458% |
|
||||
| `_actor_action_try_to_dive` | 720 | 704 | 29 / 29 | 85.18107% |
|
||||
| `_actors_searching_same_position` | 320 | 320 | 14 / 14 | 87.87611% |
|
||||
|
||||
These parks do not claim strict byte credit. They classify completed semantic
|
||||
source whose remaining differences have resisted credible source-level
|
||||
control.
|
||||
|
||||
## Evidence reviewed
|
||||
|
||||
Before parking, this pass read the preserved Claude, Fable, and integration
|
||||
records:
|
||||
|
||||
- `docs/object_matching_logs/actions_obj.md`;
|
||||
- `docs/object_matching_logs/actions_obj_codex_closure.md`;
|
||||
- `docs/object_matching_logs/actions_obj_jonas_policy_reconciled_replay_20260827.md`;
|
||||
- `docs/object_matching_logs/actions_obj_jonas_large_natural_pair_no_fake_20260830.md`;
|
||||
- `docs/object_matching_logs/actions_obj_jonas_pursuit_name_recovery_20260831.md`;
|
||||
- `docs/object_matching_logs/actions_obj_semantic_private_names_20260831.md`;
|
||||
- the campaign throughput and methodology records.
|
||||
|
||||
`tools/campaign/branch_sweep.py source/ai/actions` compiled nine unique source
|
||||
blobs reachable from the registered campaign branches. None exceeded the
|
||||
canonical 58-exact/5-residual/0-unwritten frontier. Older blobs either failed
|
||||
against the current headers or regressed to 54 or fewer exact functions.
|
||||
|
||||
## Anti-fake ruling
|
||||
|
||||
The only known strict form of `_actor_action_handle_danger_avoidance` uses an
|
||||
empty positive `if` arm followed by all meaningful work in `else`. That form
|
||||
was independently identified as an exact-score-only topology and previously
|
||||
reverted. It remains rejected. The retained production source uses the
|
||||
coherent negative predicate, accepts the honest 16-byte envelope difference,
|
||||
and contains no volatile/register steering, barriers, pragmas, artificial
|
||||
dependencies, inert carriers, undefined behavior, or nonsensical branches.
|
||||
|
||||
The other four retained bodies are likewise ordinary typed C. Their residuals
|
||||
are compiler allocation, private convention, frame coloring, instruction
|
||||
scheduling, or translation-unit-context differences documented in the parked
|
||||
manifest. No inline assembly is introduced, and the object emits no
|
||||
`point_from_line3d` COMDAT.
|
||||
|
||||
## Reopen conditions
|
||||
|
||||
Reopen a parked function only for one of:
|
||||
|
||||
- authenticated January source or local-variable records;
|
||||
- a compatible original compiler/QFE that naturally emits the target;
|
||||
- a natural same-compiler donor with the same control-flow and lifetime shape;
|
||||
- new cross-build provenance that contradicts the retained semantics.
|
||||
|
||||
Pure score steering is not new evidence.
|
||||
|
||||
## Verification
|
||||
|
||||
The admission commands for this closeout are:
|
||||
|
||||
```text
|
||||
python -B tools/campaign/gate.py source/ai/actions
|
||||
python -B -m tools.parked_functions
|
||||
python -B tools/fake_match_scan.py source/ai/actions.c
|
||||
git diff --check
|
||||
```
|
||||
|
||||
The final integration wave must additionally run the full canonical Ninja,
|
||||
semantic, regression, test, and COMDAT checks before publishing.
|
||||
@@ -1,145 +0,0 @@
|
||||
# `actions.obj` opus5 100K wave D: park re-investigation (2026-09-14)
|
||||
|
||||
## Scope and provenance
|
||||
|
||||
- Translation unit `source/ai/actions.c`, target `build/split/source/ai/actions.obj`
|
||||
(January 2002 Xbox debug build, XDK 3911 / VC7 13.00.9254, repository flags
|
||||
`/O2 /Oy- /DDEBUG /Dxbox`, unchanged).
|
||||
- Lane worktree `C:\halo-worktrees\opus5-100k-consolidated-20260914`, wave D
|
||||
(park re-investigation, brief sections 9-10). Worker notes:
|
||||
`scratch/workersD/actions.md`; scratch candidates in `scratch/workersD/actions/`.
|
||||
- The prepared Ghidra and map-atlas files for actions.obj did not exist, so the
|
||||
evidence was the January COFF (alndiff, relocations, frame census), the HCEA and
|
||||
Stian lifts (names and behavior only), and **new** HCEX.pdb (SHIP) local-variable
|
||||
records read with `DIA2Dump.exe -sym <function>`.
|
||||
- Ledgers read first: `actions_obj.md`, `actions_obj_codex_closure.md`,
|
||||
`actions_obj_jonas_policy_reconciled_replay_20260827.md`,
|
||||
`actions_obj_jonas_large_natural_pair_no_fake_20260830.md`,
|
||||
`actions_obj_jonas_pursuit_name_recovery_20260831.md`,
|
||||
`actions_obj_semantic_private_names_20260831.md`,
|
||||
`actions_obj_large_fuzzy_closeout_20260901.md`, plus the five `config/parked.json`
|
||||
entries.
|
||||
|
||||
## Validated baseline (lane HEAD)
|
||||
|
||||
`== exact 58 residual 5 unwritten 0 (of 63 listed)`, and all five residuals are
|
||||
parked (locked):
|
||||
|
||||
| Function | Target | Base | Relocs | Base normalized sha16 |
|
||||
| --- | ---: | ---: | ---: | --- |
|
||||
| `_actor_action_handle_danger_avoidance` | 1520 | 1504 | 34/34 | b1d5ecaf33b392f8 |
|
||||
| `_actor_action_handle_lost_contact` | 1872 | 1872 | 55/55 | 0e96d40ea2f38122 |
|
||||
| `_actor_action_handle_vehicle_entry` | 960 | 960 | 22/22 | 80e7bf257e70635f |
|
||||
| `_actor_action_try_to_dive` | 720 | 704 | 29/29 | 1489a21aa830ee03 |
|
||||
| `_actors_searching_same_position` | 320 | 320 | 14/14 | 844a679f805ae87f |
|
||||
|
||||
## Result
|
||||
|
||||
The production file is **unchanged** (every target is parked). Two parks were made
|
||||
strict EXACT in scratch with natural source and are proposed for re-opening. The
|
||||
combined candidate `scratch/workersD/actions/c2.c` (diff
|
||||
`scratch/workersD/actions/park_reopen_c2.diff`) gates at
|
||||
**60 exact / 3 residual / 0 unwritten**: every baseline EXACT row stays EXACT, the
|
||||
`_point_from_line3d` guard passes, the three remaining parks keep their
|
||||
`measurements.base` size/relocations/sha, the owner census against
|
||||
`build/base` differs only in the danger-avoidance size and `.debug$S`
|
||||
(`__FILE__` artifact), and `tools/fake_match_scan.py` reports 0 leads.
|
||||
|
||||
### `_actor_action_handle_danger_avoidance` - scratch strict EXACT (1520/34, sha 50e4161c4fc3e7ba)
|
||||
|
||||
- January facts: the frame is `sub esp,0xac` (base `0xb0`); January reuses the
|
||||
`actor_index` home `[ebp+8]` for the ledge distance and `[ebp+0xb]` for
|
||||
`escape_is_ledge` because `actor_index` is in EBX from `find_escape` onward, and it
|
||||
places the outside-zone diagnostic block at +0x2c2 as the fall-through of the
|
||||
`path_re_enters_danger = FALSE` store, reached by a backward `je` from the body
|
||||
test.
|
||||
- Source change (one shape): the outside-zone record became the `else` arm of
|
||||
`if (body_within_danger) { urgency, communication, escape and dive handling } else { outside-zone diagnostic }`
|
||||
instead of `if (!body_within_danger) { ...; goto try_avoid_action; }` followed by the handling.
|
||||
- This is **not** the previously rejected empty-then form: the then-arm holds all of
|
||||
the avoidance work, there is no empty arm and no inverted predicate.
|
||||
|
||||
### `_actor_action_handle_lost_contact` - scratch strict EXACT (1872/55, sha 1b2dca7a160e3658)
|
||||
|
||||
New provenance: the HCEX.pdb local records for this function group the pursuit
|
||||
desire locals (`is_pursuit_controller`, `group_pursuit_restriction`,
|
||||
`when_to_search_at_target`, `controlled_by_group_pursuit`, `when_to_pursue`,
|
||||
`when_to_search_pursuit`, `controlling_group_pursuit`) in a nested block. They also
|
||||
put `evaluation_context`, `new_firing_position`, `path_state_valid` and
|
||||
`previous_owner` in one inner block, and give each action change its own block-local
|
||||
`new_state_data`. The January byte facts agree:
|
||||
|
||||
| Source change | January evidence |
|
||||
| --- | --- |
|
||||
| desire locals into the `if (!orphan ...)` block | `pursuit_from_uncover` shares frame cell -5 with `controlled_by_group_pursuit` (sibling scopes) |
|
||||
| `pursue_tenacious` declared first | init store order starts with `[ebp-0x12]` |
|
||||
| `firing_position_index` / `pursuit_from_uncover` declared in `if (allow_pursuit)` | `or edi,-1` / `mov [ebp-5],0` emitted after the `allow_pursuit` test |
|
||||
| no `search_started` local (call results tested directly) | no slot, `test al,al` on the call result |
|
||||
| `search`, `candidate`, `previous_owner_actor_index`, `position_flags` (uninitialised out-parameters) declared in the select block | no init stores; the last store-schedule swap disappears only with this scoping |
|
||||
| `orphan == NULL ? NONE : orphan->last_perceived_time` (both sites) | NONE arm is the fall-through at both sites |
|
||||
| block-local `last_perceived_time` before the encounter test | value computed before `cmp encounter_index,-1` |
|
||||
| `actor->firing_positions.` direct access, count reset before prop index | count store precedes the CSE'd prop store; a `firing_positions->` pointer store kills the CSE (measured 1888 bytes) |
|
||||
|
||||
Ablation in the final context: restoring the original
|
||||
`find_path_direction_from_target = actor->target.target_prop_index != NONE` stays
|
||||
EXACT (kept). Reverting the polarity, the block-local time, or the count-first order
|
||||
each loses exactness. Restoring the pointer local breaks the size.
|
||||
|
||||
## Experiment matrix for the remaining parks (scratch only, all reverted)
|
||||
|
||||
| Function | Shape | Result |
|
||||
| --- | --- | --- |
|
||||
| searching_same_position | A single-exit if/else-if chain | 116 insns, same allocation, loses an epilogue |
|
||||
| searching_same_position | B `result = (distance < 0.49)` | identical to A |
|
||||
| searching_same_position | C base CFG with `return result` | 123 insns, allocation unchanged |
|
||||
| searching_same_position | D declare+init + C | identical to base |
|
||||
| vehicle_entry | V3 enclosing positive guard | identical to base |
|
||||
| vehicle_entry | V1/V2 literal success returns (diagnostic) | result const-folded, 944 bytes |
|
||||
| vehicle_entry | V4 `result = TRUE; goto result_exit;` (diagnostic) | identical to base |
|
||||
| vehicle_entry | V5 block-local `new_state_data` (HCEX.pdb) | identical to base |
|
||||
| try_to_dive | D2 HCEX locals, `real_vector2d evade_vector`, if/else tail, no `local_actor_index` copy | 704; evade-vector slots and tail now match; still not inlined |
|
||||
| try_to_dive | D3 perpendicular scalars, i-first dots | 720 size, x87 load order still lazy |
|
||||
| try_to_dive | D3c scalars before best_* inits | identical to D3 |
|
||||
| try_to_dive | probe: a `short animation_impulse` prototype (diagnostic, not landable) | reproduces January's 16-bit impulse push exactly |
|
||||
|
||||
## Residual classification (remaining parks)
|
||||
|
||||
- `_actors_searching_same_position`: register allocation decided before `result`'s first
|
||||
definition (actor pointer EBX vs spill, ECX/EDX swap of the second pursuit location).
|
||||
January returns the result byte on every path. No single-exit, paren or inline law
|
||||
moves it.
|
||||
- `_actor_action_handle_vehicle_entry`: three differences only. January keeps an
|
||||
unfolded zero-materialised `result` (DL) for the three guard exits while its success
|
||||
path returns constant 1; base cross-jumps the guard exit into the success tail. There
|
||||
is also one integer store one x87 instruction early. Same family as the
|
||||
zero-register-pinning residual.
|
||||
- `_actor_action_try_to_dive`: entry/parameter register allocation (January keeps
|
||||
`actor_index` in ESI and reloads `alignment_vector` per case), perpendicular x87 load
|
||||
order, and a 16-bit `unit_test_animation_impulse` argument. HCEX.pdb gives
|
||||
`(long unit_index, short animation_impulse)`, but units.c's exact definition keeps a
|
||||
full-width parameter, so this is a header-prototype question.
|
||||
|
||||
## Do-not-repeat
|
||||
|
||||
- The empty-then `if (body_within_danger) {} else {...}` form (fake; superseded by the
|
||||
structured if/else above).
|
||||
- Declaration-order-only and pointer-local experiments on lost_contact (the residual was
|
||||
scoping and aliasing, now closed).
|
||||
- Tail spellings V1-V5 on vehicle_entry; shapes A-D on searching_same_position.
|
||||
- Scalar perpendicular locals on dive (VC7 forwards them lazily).
|
||||
|
||||
## Reopen criteria
|
||||
|
||||
- vehicle_entry / searching_same_position: authoritative January locals or a natural
|
||||
same-compiler donor for the guard-exit zero or the allocation (HCEX.pdb has no stack
|
||||
locals for searching).
|
||||
- try_to_dive: an orchestrator decision on the `short animation_impulse` prototype
|
||||
seen by actions.c (the declaration-count law applies to units.h), then a natural form
|
||||
for the perpendicular scores and the entry allocation.
|
||||
|
||||
## Disposition
|
||||
|
||||
- Production `source/ai/actions.c`: unchanged, 58/63 strict exact, five parks intact.
|
||||
- Proposed park reopen (orchestrator lands in a dedicated commit):
|
||||
`_actor_action_handle_danger_avoidance` and `_actor_action_handle_lost_contact` from
|
||||
`scratch/workersD/actions/c2.c`.
|
||||
@@ -1,84 +0,0 @@
|
||||
# `actions.obj` opus5 150K wave 2: park triage (2026-09-14)
|
||||
|
||||
## Scope
|
||||
|
||||
- Translation unit: `source/ai/actions.c`.
|
||||
- Worker notes: `scratch/workers/actions_action_flee_etc.md`.
|
||||
- Ledgers read:
|
||||
- `actions_obj.md`
|
||||
- `actions_obj_codex_closure.md`
|
||||
- `actions_obj_jonas_policy_reconciled_replay_20260827.md`
|
||||
- `actions_obj_jonas_large_natural_pair_no_fake_20260830.md`
|
||||
- `actions_obj_jonas_pursuit_name_recovery_20260831.md`
|
||||
- `actions_obj_semantic_private_names_20260831.md`
|
||||
- `actions_obj_large_fuzzy_closeout_20260901.md`
|
||||
- `actions_obj_opus5_100k_waveD_20260914.md`
|
||||
- 100K lane worker notes also read: `scratch/workersD/actions.md` (shapes A-D, V1-V5, D2/D3/D3c/D3probe).
|
||||
- Inherited exact functions, not touched: `_actor_action_handle_lost_contact` and `_actor_action_handle_danger_avoidance`.
|
||||
|
||||
## Baseline and result
|
||||
|
||||
The baseline and the final gate are identical: `== exact 60 residual 3 unwritten 0`. The guard passes and park drift is 0. The production file is **unchanged**.
|
||||
|
||||
| Function | Outcome | Reason |
|
||||
| --- | --- | --- |
|
||||
| `_actor_action_try_to_dive` (720) | OWNER-BLOCKED | January pushes a 16-bit `animation_impulse` (+0x185 `xor ecx,ecx; mov cx,[esi-2]`). HCEX.pdb gives `unit_test_animation_impulse(long, short)`, but `units.h:638` declares `long`, and the definition is in protected `units.c`. Any probe has to rename the callee symbol, so a strict measurement is impossible. The prerequisite is the 100K lane's units.h + units.c proposal. |
|
||||
| `_actor_action_handle_vehicle_entry` (960) | NOT-LANDED (scratch closer body) | See the vehicle-entry section below. |
|
||||
| `_actors_searching_same_position` (320) | SKIPPED-EXHAUSTED | HCEX.pdb has parameters only. The function is static in HCEX but public in the January PDB publics (rva 59216). Shapes A-D already cover the single-exit and result forms. |
|
||||
|
||||
## `_actor_action_handle_vehicle_entry`: single-exit re-investigation
|
||||
|
||||
Scratch only. The best candidate is `scratch/workers/actions_action_flee_etc/act_ve3.c` (diff: `act_ve3.diff`).
|
||||
|
||||
### Lever
|
||||
|
||||
The lever comes from this wave's flood measurements. VC7 splits a return join into constant epilogues where each path's value is a known constant. It keeps the live register copy (`dl`) only on paths where the initialiser is still enregistered.
|
||||
|
||||
### Shapes
|
||||
|
||||
**VE3.** A fully structured single exit (SINGLE-EXIT LAW), with no gotos or labels:
|
||||
|
||||
```c
|
||||
if (!(flee && panic_type > 0) && action != obey && !(last_vehicle_check_time != NONE && last_vehicle_check_time + 45 >= current_time))
|
||||
{
|
||||
...
|
||||
if (best_vehicle_index == NONE && certain_combat_timer >= 60)
|
||||
{
|
||||
for (slot = 0; ...) { ... }
|
||||
}
|
||||
if (best_vehicle_index != NONE && action_vehicle_setup_impromptu(...))
|
||||
{
|
||||
actor_action_change(...);
|
||||
result = TRUE;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
```
|
||||
|
||||
Result: 960/22, sha 9139bfc47fc7de8a.
|
||||
|
||||
- The success tail is now January's `mov al,1`. The previous build merged it as `mov dl,1 ... mov al,dl`.
|
||||
- Three hunks remain. Two are the FALSE epilogue copies in swapped order: January places the late-exit `xor al,al` copy first and the guard `mov al,dl` copy last, while our build does the reverse. The third is the prop-loop `best_vehicle_index` store, emitted one x87 instruction before January's position (before `fmul st(1)` instead of after it).
|
||||
|
||||
**Other shapes:**
|
||||
|
||||
| Shape | Result |
|
||||
| --- | --- |
|
||||
| VE1: the late `return FALSE` statements jump to the common return | identical to VE3 |
|
||||
| VE4: `result` declared first | worse |
|
||||
| VE5: De Morgan'd guard | identical to VE3 |
|
||||
| VE6: `best_vehicle_index` stored before the distance | identical to VE3 |
|
||||
|
||||
### Outcome
|
||||
|
||||
The function is not exact, so the park stays. The whole-TU rows are unchanged, the other parks are OK, the guard passes, and the fake scan reports 0 leads.
|
||||
|
||||
**Reopen criterion:** start from `act_ve3.c`. A source fact is still needed that orders the two FALSE epilogue copies and schedules the integer store after the x87 multiply.
|
||||
|
||||
## Checks
|
||||
|
||||
On the real file:
|
||||
|
||||
- owner census: no new or dropped owners;
|
||||
- `fake_match_scan`: 0 leads;
|
||||
- `git diff --stat -- source/ai/actions.c`: empty.
|
||||
@@ -1,145 +0,0 @@
|
||||
# `actions.obj` opus5 150K wave 3: law-detector pass over the three parks (2026-09-14)
|
||||
|
||||
## Scope
|
||||
|
||||
- Translation unit `source/ai/actions.c`; target `build/split/source/ai/actions.obj`.
|
||||
- Worker notes: `scratch/workers/w3_actions_path_obstacle_avoidance_etc.md`; candidates in
|
||||
`scratch/workers/w3_actions_path_obstacle_avoidance_etc/`.
|
||||
- Ledgers read: `actions_obj.md`, `actions_obj_codex_closure.md`,
|
||||
`actions_obj_jonas_policy_reconciled_replay_20260827.md`,
|
||||
`actions_obj_jonas_large_natural_pair_no_fake_20260830.md`,
|
||||
`actions_obj_jonas_pursuit_name_recovery_20260831.md`,
|
||||
`actions_obj_semantic_private_names_20260831.md`, `actions_obj_large_fuzzy_closeout_20260901.md`,
|
||||
`actions_obj_opus5_100k_waveD_20260914.md`, `actions_obj_opus5_150k_w2_20260914.md`, the 100K lane
|
||||
`scratch/workersD/actions.md` (with its D3probe and searching_A-D bodies), the w2 worker notes, and the
|
||||
actors / ai_communication ledgers that carry the pending P1 `short animation_impulse` packet.
|
||||
- Inherited exact functions, not touched: `_actor_action_handle_lost_contact`,
|
||||
`_actor_action_handle_danger_avoidance`.
|
||||
|
||||
## Baseline and result
|
||||
|
||||
Baseline and final real-file gate are identical: `== exact 60 residual 3 unwritten 0`, guard passes,
|
||||
park drift 0, owner census clean, `fake_match_scan` 0 leads. The production file is **unchanged**
|
||||
(`git diff --stat` empty).
|
||||
|
||||
| Function | Padded | Outcome |
|
||||
| --- | ---: | --- |
|
||||
| `_actor_action_try_to_dive` | 720 | **PARK-REOPEN-PROPOSED**: strict EXACT in scratch under the pending P1 units.h prototype |
|
||||
| `_actor_action_handle_vehicle_entry` | 960 | NOT-LANDED (2 new shapes, no lever) |
|
||||
| `_actors_searching_same_position` | 320 | NOT-LANDED (one A10 detector shape, worse) |
|
||||
|
||||
## `_actor_action_try_to_dive`: strict EXACT pending P1
|
||||
|
||||
### Measurement method (new)
|
||||
|
||||
w2 recorded this function as unmeasurable because every probe had to rename the callee. This wave used a
|
||||
shadow header tree instead: `shadow_short/units/units.h` is the current `units.h` with exactly the P1 change
|
||||
(`short animation_impulse` in `unit_test_animation_impulse` and `unit_start_animation_impulse`), placed first on
|
||||
the include path by `shadow_gate.py`. The callee keeps its real symbol, so `section_infos_equal` is strict.
|
||||
|
||||
### January evidence and the laws that explain it
|
||||
|
||||
1. **A4 helper routing.** Escape-direction cases 2 and 3 are `fld [eax+4]; mov ecx,[eax]; fstp [ebp-0x1c];
|
||||
mov [ebp-0x20],ecx`. Explicit component copies give four integer moves. An inlined
|
||||
`set_real_vector2d(&evade_vector, alignment_vector->i, alignment_vector->j)` reproduces the x87 form. The
|
||||
callee `actor_moving.c:1343-1360` spells the identical evasion switch with `set_real_vector2d`.
|
||||
2. **A4 + A22 dot canonicalisation.** `fld facing.j; fchs; fld facing.i` happen before the first dot product
|
||||
and are consumed later by `fmul; fxch; fmul; faddp`. That is a left-perpendicular vector built by one
|
||||
`set_real_vector2d(&left, -facing.j, facing.i)` and two `dot_product2d` calls (j term first).
|
||||
3. **Single-exit law.** January keeps `actor_index` in ESI (`mov edi,esi` for the debug index) and reloads
|
||||
`alignment_vector` from its parameter slot in every case. The whole dive therefore sits in the
|
||||
lower-frequency body of `if (vehicle_index == NONE && actor_move_try_evasion_direction(...))`, with an
|
||||
`else { cannot_move; result = FALSE; }` arm. Inside it, `if (best_animation == NONE) {...} else {...}` sets
|
||||
`result`, and the function has one `return result;`.
|
||||
4. **P1.** The impulse push `xor ecx,ecx; mov cx,[esi-2]` is a 16-bit prototype parameter. HCEX.pdb has
|
||||
`unit_test_animation_impulse(long, short)`.
|
||||
|
||||
### Shapes
|
||||
|
||||
All shapes were measured under the shadow P1 header.
|
||||
|
||||
| Shape | Result |
|
||||
| --- | --- |
|
||||
| dv0: D3probe body with the real callee name | 720/29 sha; entry allocation, case 2/3 copies and scores differ |
|
||||
| dv1: + `set_real_vector2d` evasion switch | cases 2/3 now January's x87 form |
|
||||
| dv_s2 / dv_s3: + `left` vector (explicit or `dot_product2d`, byte-identical) | score block equal |
|
||||
| dv_e1: + single-exit nesting | **strict EXACT**, 61 exact |
|
||||
| dv_f: block-scoped declare+init moved before the switch | worse (60), reverted |
|
||||
| dv_f2 / dive_reopen.c: dv_e1 + enum constants, `left` at function scope | **strict EXACT**; the bare block was measured inert and dropped |
|
||||
|
||||
The enum constants are `_actor_evade_left/right/forward/back` and `_ai_communication_dive` (= 44, counted in
|
||||
`ai_communication.h`).
|
||||
|
||||
### Candidate
|
||||
|
||||
`scratch/workers/w3_actions_path_obstacle_avoidance_etc/dive_reopen.c`, diff `dive_reopen.diff`. It is the
|
||||
current real file plus:
|
||||
|
||||
- the new dive body;
|
||||
- the TU-local `enum actor_evade_direction` completed with `_actor_evade_forward` and `_actor_evade_back`
|
||||
(values 2 and 3, as in the complete copy in `actor_moving.c`; `_actor_evade_random` keeps value 4), with a
|
||||
disclosure comment naming the other copy. No shared owner header declares this enum.
|
||||
|
||||
Measurements:
|
||||
|
||||
- **Shadow P1:** 720/29, sha `2548ce8b22f46d48` == target; 61/63 exact. The other two parks are unchanged,
|
||||
and `danger_avoidance`'s `unit_test_animation_impulse` call stays EXACT under the short prototype.
|
||||
- **Current headers:** 720/29, sha `b2b7a2731165dff9`. The only code hunk is `movsx ecx,word [esi-2]` against
|
||||
January's `xor ecx,ecx; mov cx,[esi-2]`, so P1 is the sole prerequisite.
|
||||
- **Both gates:** all 60 baseline-EXACT rows stay EXACT and the guard passes.
|
||||
- **Checks:** owner census differs from `build/base` only in `$L` internal labels; `fake_match_scan` reports
|
||||
0 leads.
|
||||
|
||||
### What the programmer meant
|
||||
|
||||
If the actor is on foot and an evasion direction exists, the evade vector is built from the requested side (the
|
||||
same idiom as the evasion routine). Each dive animation's direction is scored by projecting the evade vector onto
|
||||
the facing vector and its left perpendicular. The best playable animation wins and plays. The debug decision code
|
||||
is recorded, and a single result is returned.
|
||||
|
||||
## `_actor_action_handle_vehicle_entry`
|
||||
|
||||
Re-reading January's stream shows that w2's VE3 already has January's semantics:
|
||||
|
||||
- the guard exits return the `xor dl,dl` register copy;
|
||||
- the late exits return a constant `xor al,al`;
|
||||
- success returns `mov al,1`.
|
||||
|
||||
What remains is the layout order of the two duplicated FALSE epilogues (January puts the late-exit copy first) and
|
||||
one `mov [ebp-4],ecx` emitted after `fmul st(1)` in January.
|
||||
|
||||
No w2 law has this fingerprint (A3a is already reproduced; A10/A13/A14/A16/A20 do not apply).
|
||||
|
||||
| Shape | Result |
|
||||
| --- | --- |
|
||||
| VE7: guards as `goto result_exit` to a label before the single return | byte-identical to VE3 |
|
||||
| VE8: guards as early `return result;` | 928 bytes, result homed at `[ebp-1]`; reverted |
|
||||
|
||||
A `SQUARE`-style parenthesised form has no genuine macro and is inadmissible.
|
||||
|
||||
**Reopen:** a source fact that orders the FALSE epilogue copies or the store after the x87 multiply. Do not repeat
|
||||
V1-V5 or VE1-VE8.
|
||||
|
||||
## `_actors_searching_same_position`
|
||||
|
||||
The w2 do-not-repeat entry allowed only a genuinely new law.
|
||||
|
||||
- **Law checked:** A10 (a default initializer plus conditional reassignment gives a stack home). The fingerprint is
|
||||
present: base homes result at `[ebp-1]`, January keeps it in BL.
|
||||
- **SS1:** assigning `result` on every leaf gives 304/14. The stack home disappears as A10 predicts, but VC7
|
||||
const-splits the result instead of pinning BL, and the actor pointer stays in EBX. Worse; reverted.
|
||||
- **Residual:** the callee-saved choice diverges before the result initializer (second pursuit location DX/ECX
|
||||
against CX/EDX).
|
||||
|
||||
**Reopen:** authoritative locals or a fact that moves that choice. Do not repeat waveD A-D or SS1.
|
||||
|
||||
## Orchestrator proposals
|
||||
|
||||
There is no new header text. This wave adds one strict unlock to the pending **P1** packet
|
||||
(`ai_communication_obj_opus5_150k_w3_20260914.md` proposal 1; actors waveD proposal 2):
|
||||
|
||||
1. Change `long animation_impulse` to `short animation_impulse` in both `units.h` prototypes.
|
||||
2. Match the `units.c` definitions (PROTECTED) and the static helper.
|
||||
3. In the same commit, unpark `_actor_action_try_to_dive` with the `dive_reopen.c` body and TU enum.
|
||||
|
||||
Consumers are the 66 `units.h` includers already listed for P1.
|
||||
Loaded 100 of 6748 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user