From d826795bbbd755203223a7ae52d3d876750b6024 Mon Sep 17 00:00:00 2001 From: 0xrsydn Date: Wed, 23 Sep 2026 18:25:36 +0700 Subject: [PATCH] docs(api): record reward observation audit and deployment status --- docs/COMPOSITE_REWARDS.md | 2 + docs/research/16-reward-api-audit.md | 130 +++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 docs/research/16-reward-api-audit.md diff --git a/docs/COMPOSITE_REWARDS.md b/docs/COMPOSITE_REWARDS.md index 74aa154..746677c 100644 --- a/docs/COMPOSITE_REWARDS.md +++ b/docs/COMPOSITE_REWARDS.md @@ -68,3 +68,5 @@ selection, and recording. No live game or model connection is needed. See [the research proposal](research/15-composite-card-policy-proposal.md) for the full algorithm and evaluation plan. This implementation is its first, limited stage. +The [reward API audit](research/16-reward-api-audit.md) identifies the observation +changes needed before completing take-versus-skip decisions. diff --git a/docs/research/16-reward-api-audit.md b/docs/research/16-reward-api-audit.md new file mode 100644 index 0000000..f867142 --- /dev/null +++ b/docs/research/16-reward-api-audit.md @@ -0,0 +1,130 @@ +# Reward decision API audit + +Status: offline source audit and proposed follow-up. No runtime verification, +policy change, or approved API schema. Audited after commit `baf0d529`. +The installed game and mod may differ from the vendored source. + +## Findings + +| Question | Source evidence | Conclusion | +| --- | --- | --- | +| Does ordinary state include the permanent deck? | `vendor/STS2MCP/McpMod.StateBuilder.cs`, `BuildPlayerState` | No. It exposes hand and combat piles only while combat is active. The earlier comment claiming deck inclusion is misleading. | +| Does compendium expose the current deck? | `vendor/STS2MCP/McpMod.Compendium.cs`, `BuildCurrentRunContext` | No. It reads selected save metadata and run identity, not current deck cards. Historical `deck_count` is not a current deck. | +| Can wiki reconstruct deck ownership? | `vendor/STS2MCP/McpMod.Wiki.cs`, `BuildWikiSearch` | No. Search covers profile-discovered card/relic definitions, not owned instances. | +| What identifies offered cards? | `BuildCardRewardState`, `BuildCardInfo` | Observation-local index, model ID, name, type, cost, star cost, description, rarity, upgrade flag, keywords. Model ID is not an instance ID. | +| What does `can_skip` prove? | `BuildCardRewardState` | At least one `NCardRewardAlternativeButton` was found. It does not report label, effect, visibility, or enabled state. | +| What does skipping execute? | `vendor/STS2MCP/McpMod.Actions.cs`, `ExecuteSkipCardReward` | `altButtons[0].ForceClick()`. The action does not identify or select among different alternatives. | +| Does success prove the resulting deck? | `ExecuteSelectCardReward`, `ExecuteSkipCardReward` | No. These return after sending a UI signal/click. A subsequent observation is required. | + +The source does not establish which alternative types exist in the installed game, +or whether a particular skip has resource/relic effects. Do not infer those effects +from an action named `skip_card_reward`. Do not infer a side effect exists either. + +## Limits of the current bot + +`run_state.RunContext.capture_combat` stores name counts and a summary, with +`persistent_deck: false`. Generated cards and temporary upgrades can remain in +that evidence. Draw-pile display order is sorted, not future draw order. + +`RunContext.observe` invalidates evidence on missing run identity or a room change. +`record_result` preserves evidence when opening a card reward or skipping it. +Other accepted noncombat actions clear evidence. Thus taking another reward, +including gold, can remove the limited deck context before card selection. +This is conservative behavior, not proof that the deck changed. + +The composite policy makes no model call without scoped card evidence. With valid +scores but no clear addition, it selects the best-ranked card as a fallback. +It does not skip. A harmful addition remains possible. This is not a complete +reward policy and is not ready to replace the default. + +Skip-memory handling also assumes reward skipping can preserve card evidence. +Revisit that assumption when alternative effects become available; do not reuse +old evidence if an accepted alternative can change the deck. + +## Recommended next implementation: observation support first + +Prefer an in-memory permanent-deck snapshot in the normal state response. +Do not add a second AI agent, reconstruct ownership from wiki results, or quietly +promote combat piles into an exact deck. A save-file parser would require separate +freshness and identity reconciliation and is not the first choice. + +The following is a proposed contract, not an existing API: + +1. Expose every permanent card instance, including duplicate copies and permanent + upgrades/modifications. Preserve existing card display fields. Report unavailable + data explicitly; distinguish an empty deck from a failed read. +2. Include deck source and completeness. Read it with the ordinary observation. + Do not claim atomic run identity while identity still comes from a separate read. +3. Expose each reward alternative's observation-local action identifier, visible + label/description, enabled state, and known effect metadata. Unknown effects + stay unknown. A label alone cannot certify a side-effect-free skip. +4. Provide a matching action that targets the selected alternative. Keep indices + local to one observation, and reject absent or disabled targets. +5. Establish the actual game behavior for plain skips and reward-triggered effects + before assigning a zero baseline. Verify the game model API against the installed + version; this audit does not establish a permanent-deck member name. + +Implement these changes in the mod's maintained source first, then update the +vendored dependency deliberately. Do not modify the vendor snapshot merely to +simulate fields that the installed API cannot provide. + +## Bot integration after the observation contract + +- Prefer the reported permanent deck; retain labeled limited evidence for older APIs. +- Build candidates for each card and each supported alternative. +- Evaluate additions against the actual alternative, not an assumed free skip. +- Keep arithmetic in `policy/scoring.py`; keep effect interpretation, evidence + requirements, and acceptance rules in reward-specific code. +- Treat inadequate evidence separately from neutral utility. Score confidence alone + cannot establish that required deck or effect information exists. +- Leave the current experimental weights fixed while changing context and options. + +## Acceptance checks + +Use offline fixtures and model stubs before an authorized live verification: + +- Duplicate permanent cards survive serialization; temporary combat cards do not + become permanent cards. Permanent upgrades/modifications remain distinguishable. +- Missing deck data differs from a genuinely empty deck. +- Old APIs retain explicit limitations; no invented completeness or instance IDs. +- Plain skip, side-effecting alternatives, disabled alternatives, and multiple + alternatives map to the correct action. Unknown effects do not receive zero value. +- Harmful and neutral offers can lose to a verified plain skip. Forced selections + still produce a legal card choice. +- Accepted requests are reconciled with fresh state, including delayed transitions + and changed indices. A successful click alone does not establish the outcome. + +No live game requests, model calls, save-file reads, or vendor changes were used +for this audit. External strategy research cannot resolve these API semantics. + +## Follow-up: separate mod prototype + +With user approval, a separate Jujutsu checkout was created at +`/Users/rasyidanakbar/sts2-mcp`, based on upstream `55e064850a68f3b4cde7e5fd525bf9b2dec4e885`. +The extension is published at `git@git.rasyidanaf.com:0xrsydn/sts2-mcp.git`, +commit `6c4cc172794f7a7ca42b86f4122582f93321363e`. The bot now pins that revision +as the `vendor/STS2MCP` submodule. See [setup instructions](../MOD_SETUP.md). + +Inspection of installed game assemblies confirmed `Player.Deck`, alternative +option IDs, and the reward screen's option/button ordering. Standard alternative +generation creates Skip and optionally REROLL, then invokes modification hooks. +This does not certify the effects of every active Skip callback. + +The prototype exposes permanent deck membership, explicit alternative metadata, +and an indexed `select_reward_alternative` action with identity and UI guards. +Full structured modifier details and verified side-effect-free skip semantics +remain unavailable. See the mod checkout's `docs/reward-observations.md`. + +The Release build passed with no warnings or errors. Nineteen isolated UI-stub +checks passed against the new alternative source. The vendor checkout was later +updated deliberately to the published submodule revision. Bot policy is unchanged. + +A subsequent authorized deployment installed the rebuilt DLL after backing up the +previous DLL. Launching through Steam succeeded; the game log confirms mod loading +and HTTP startup. A read-only GET returned the main menu. The menu has no player +or reward data, so live permanent-deck and alternative serialization remain +unverified. No action POSTs or model calls were sent. Deployment hash and rollback +path are recorded in the mod checkout's `docs/reward-observations.md`. + +The next checkpoint requires entering a run and reaching a reward screen, then +read-only inspection of the new fields before bot integration.