ppsspp-dfx-mcp 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ppsspp_dfx_mcp-0.1.2/.github/workflows/ci.yml +53 -0
- ppsspp_dfx_mcp-0.1.2/.github/workflows/pypi-publish.yml +84 -0
- ppsspp_dfx_mcp-0.1.2/.gitignore +28 -0
- ppsspp_dfx_mcp-0.1.2/.mcp.json +15 -0
- ppsspp_dfx_mcp-0.1.2/CHANGELOG.md +54 -0
- ppsspp_dfx_mcp-0.1.2/CONTRIBUTING.md +138 -0
- ppsspp_dfx_mcp-0.1.2/LICENSE +21 -0
- ppsspp_dfx_mcp-0.1.2/PKG-INFO +347 -0
- ppsspp_dfx_mcp-0.1.2/README.md +319 -0
- ppsspp_dfx_mcp-0.1.2/SECURITY.md +35 -0
- ppsspp_dfx_mcp-0.1.2/docs/SCOPE.md +55 -0
- ppsspp_dfx_mcp-0.1.2/evals/.gitignore +4 -0
- ppsspp_dfx_mcp-0.1.2/evals/README.md +48 -0
- ppsspp_dfx_mcp-0.1.2/evals/config.yaml +18 -0
- ppsspp_dfx_mcp-0.1.2/evals/gates.py +384 -0
- ppsspp_dfx_mcp-0.1.2/evals/judge_prompt.md +34 -0
- ppsspp_dfx_mcp-0.1.2/evals/report.py +248 -0
- ppsspp_dfx_mcp-0.1.2/evals/rescore.py +59 -0
- ppsspp_dfx_mcp-0.1.2/evals/runner.py +617 -0
- ppsspp_dfx_mcp-0.1.2/evals/scenarios.yaml +378 -0
- ppsspp_dfx_mcp-0.1.2/evals/test_b2_skill.py +90 -0
- ppsspp_dfx_mcp-0.1.2/evals/test_gates.py +321 -0
- ppsspp_dfx_mcp-0.1.2/examples/addresses.yaml +51 -0
- ppsspp_dfx_mcp-0.1.2/examples/project.yaml +23 -0
- ppsspp_dfx_mcp-0.1.2/examples/scripts.manifest.yaml +42 -0
- ppsspp_dfx_mcp-0.1.2/pyproject.toml +74 -0
- ppsspp_dfx_mcp-0.1.2/scripts/_wire.py +243 -0
- ppsspp_dfx_mcp-0.1.2/scripts/audit_test_modules.py +112 -0
- ppsspp_dfx_mcp-0.1.2/scripts/check_env.py +265 -0
- ppsspp_dfx_mcp-0.1.2/scripts/dump_tool_surface.py +122 -0
- ppsspp_dfx_mcp-0.1.2/scripts/harness_latency_baseline.json +39 -0
- ppsspp_dfx_mcp-0.1.2/scripts/probe_boundary_matrix.py +1089 -0
- ppsspp_dfx_mcp-0.1.2/scripts/record_fixtures.py +269 -0
- ppsspp_dfx_mcp-0.1.2/scripts/report_schema_surface.py +240 -0
- ppsspp_dfx_mcp-0.1.2/scripts/verify_real_mcp.py +2001 -0
- ppsspp_dfx_mcp-0.1.2/scripts/verify_tool_layering_probes.py +171 -0
- ppsspp_dfx_mcp-0.1.2/skills/ppsspp-dfx/SKILL.md +94 -0
- ppsspp_dfx_mcp-0.1.2/skills/ppsspp-dfx/assets/ppsspp.ini.template +23 -0
- ppsspp_dfx_mcp-0.1.2/skills/ppsspp-dfx/references/architecture.md +84 -0
- ppsspp_dfx_mcp-0.1.2/skills/ppsspp-dfx/references/cpu-state-contract.md +121 -0
- ppsspp_dfx_mcp-0.1.2/skills/ppsspp-dfx/references/error-codes.md +75 -0
- ppsspp_dfx_mcp-0.1.2/skills/ppsspp-dfx/references/playbook/common/batch_automation.md +83 -0
- ppsspp_dfx_mcp-0.1.2/skills/ppsspp-dfx/references/playbook/common/crash_analysis.md +61 -0
- ppsspp_dfx_mcp-0.1.2/skills/ppsspp-dfx/references/playbook/common/gameplay_loop.md +107 -0
- ppsspp_dfx_mcp-0.1.2/skills/ppsspp-dfx/references/playbook/common/replay_recording.md +81 -0
- ppsspp_dfx_mcp-0.1.2/skills/ppsspp-dfx/references/playbook/common/screenshot.md +56 -0
- ppsspp_dfx_mcp-0.1.2/skills/ppsspp-dfx/references/playbook/common/smoke_test.md +58 -0
- ppsspp_dfx_mcp-0.1.2/skills/ppsspp-dfx/references/ppsspp-constraints.md +132 -0
- ppsspp_dfx_mcp-0.1.2/skills/ppsspp-dfx/references/tool-surface.md +135 -0
- ppsspp_dfx_mcp-0.1.2/skills/ppsspp-dfx/scripts/addr_convert.py +96 -0
- ppsspp_dfx_mcp-0.1.2/skills/ppsspp-dfx/scripts/decode_text.py +102 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/__init__.py +12 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/__main__.py +68 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/address.py +169 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/completions.py +140 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/config.py +239 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/core/__init__.py +1 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/core/batch_jobs.py +274 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/core/error_codes.py +77 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/core/game_state_observer.py +747 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/core/launcher.py +560 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/core/primitives.py +20 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/core/proc.py +78 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/core/registers.py +83 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/core/stepping.py +429 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/core/transport.py +479 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/core/ws_contract.py +1136 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/errors.py +738 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/instructions.py +83 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/logging.py +109 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/middleware.py +155 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/__init__.py +5 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/analyze.py +54 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/assemble.py +29 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/batch_step.py +149 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/breakpoint.py +29 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/evaluate.py +27 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/gpu_record.py +65 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/gpu_stats.py +81 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/input.py +55 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/memory.py +65 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/memory_info_search.py +53 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/memory_map.py +24 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/query.py +34 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/replay.py +230 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/screenshot.py +57 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/search_disasm.py +31 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/session.py +110 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/smoke.py +33 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/state_observer.py +93 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/step.py +39 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/workflow.py +87 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/models/write_register.py +26 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/prompts.py +167 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/recipes/__init__.py +7 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/resources.py +101 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/scripts/__init__.py +7 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/scripts/record_fixtures.py +154 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/server.py +641 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/service/__init__.py +11 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/service/capture.py +686 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/service/debug_client.py +1816 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/service/memory_protection.py +73 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/session/__init__.py +14 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/session/client_helper.py +433 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/session/safe_boot.py +170 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/session/session_manager.py +1312 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/spec/__init__.py +1 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/spec/script_manifest.py +356 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/__init__.py +8 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/_common.py +265 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/analyze.py +314 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/assemble.py +221 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/batch_step.py +710 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/breakpoint.py +422 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/evaluate.py +127 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/gpu_record.py +120 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/gpu_stats.py +89 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/input.py +415 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/introspect.py +124 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/list_addresses.py +150 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/memory.py +797 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/memory_info_search.py +141 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/memory_map.py +85 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/query.py +344 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/replay.py +519 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/screenshot.py +451 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/script.py +554 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/search_disasm.py +259 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/session.py +313 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/smoke.py +168 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/state_observer.py +410 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/step.py +211 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/workflows.py +565 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/tools/write_register.py +113 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/__init__.py +5 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/_base.py +52 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/_contract.py +145 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/analyze.py +65 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/assemble.py +84 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/batch_step.py +169 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/breakpoint.py +47 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/evaluate.py +50 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/gpu_record.py +82 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/gpu_stats.py +77 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/input.py +58 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/introspect.py +38 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/memory.py +198 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/memory_info_search.py +70 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/memory_map.py +79 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/query.py +125 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/replay.py +99 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/screenshot.py +93 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/script.py +173 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/search_disasm.py +69 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/session.py +152 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/smoke.py +39 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/state_observer.py +127 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/step.py +64 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/workflow.py +175 -0
- ppsspp_dfx_mcp-0.1.2/src/ppsspp_dfx_mcp/views/write_register.py +41 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/cpu.breakpoint.add.json +16 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/cpu.breakpoint.list.json +24 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/cpu.breakpoint.remove.json +15 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/cpu.getAllRegs.json +630 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/cpu.status.json +17 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/cpu.stepping.json +31 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/game.status.json +19 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/hle.func.add.json +19 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/hle.func.list.json +34685 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/hle.module.list.json +21 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/hle.thread.list.json +165 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/memory.base.json +14 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/memory.disasm.json +189 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/memory.mapping.json +127 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/memory.read.json +17 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/memory.readString.json +16 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/memory.read_u32.json +16 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/memory.searchDisasm.json +17 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/fixtures/version.json +15 -0
- ppsspp_dfx_mcp-0.1.2/tests/cassettes/real_ppsspp.jsonl +23 -0
- ppsspp_dfx_mcp-0.1.2/tests/conftest.py +93 -0
- ppsspp_dfx_mcp-0.1.2/tests/contract_recorder/__init__.py +201 -0
- ppsspp_dfx_mcp-0.1.2/tests/contract_recorder/fixture_loader.py +133 -0
- ppsspp_dfx_mcp-0.1.2/tests/contract_recorder/test_fixture_loader.py +238 -0
- ppsspp_dfx_mcp-0.1.2/tests/fake_transport/__init__.py +3 -0
- ppsspp_dfx_mcp-0.1.2/tests/fake_transport/fake_transport.py +306 -0
- ppsspp_dfx_mcp-0.1.2/tests/fake_transport/test_fake_transport.py +379 -0
- ppsspp_dfx_mcp-0.1.2/tests/fake_transport/test_write_overlay.py +69 -0
- ppsspp_dfx_mcp-0.1.2/tests/integration/__init__.py +0 -0
- ppsspp_dfx_mcp-0.1.2/tests/integration/conftest.py +625 -0
- ppsspp_dfx_mcp-0.1.2/tests/integration/test_check_cpu_state_rewire.py +257 -0
- ppsspp_dfx_mcp-0.1.2/tests/integration/test_game_state_observer_integration.py +796 -0
- ppsspp_dfx_mcp-0.1.2/tests/integration/test_lifespan_integration.py +212 -0
- ppsspp_dfx_mcp-0.1.2/tests/integration/test_mcp_inspector_e2e.py +312 -0
- ppsspp_dfx_mcp-0.1.2/tests/integration/test_mem_bp_range_watch.py +41 -0
- ppsspp_dfx_mcp-0.1.2/tests/integration/test_real_mcp_matrix.py +126 -0
- ppsspp_dfx_mcp-0.1.2/tests/integration/test_real_ppsspp_e2e.py +324 -0
- ppsspp_dfx_mcp-0.1.2/tests/integration/test_record_replay_roundtrip.py +319 -0
- ppsspp_dfx_mcp-0.1.2/tests/integration/test_script_exposure_sync.py +436 -0
- ppsspp_dfx_mcp-0.1.2/tests/integration/test_script_manifest_integration.py +223 -0
- ppsspp_dfx_mcp-0.1.2/tests/integration/test_session_lifecycle_integration.py +275 -0
- ppsspp_dfx_mcp-0.1.2/tests/mcp_inspector/__init__.py +15 -0
- ppsspp_dfx_mcp-0.1.2/tests/mcp_inspector/conftest.py +206 -0
- ppsspp_dfx_mcp-0.1.2/tests/mcp_inspector/test_protocol_surface.py +119 -0
- ppsspp_dfx_mcp-0.1.2/tests/mcp_inspector/test_resources_prompts.py +66 -0
- ppsspp_dfx_mcp-0.1.2/tests/mcp_inspector/test_server_lifecycle.py +124 -0
- ppsspp_dfx_mcp-0.1.2/tests/mcp_inspector/test_tools_call.py +119 -0
- ppsspp_dfx_mcp-0.1.2/tests/mcp_inspector/test_tools_call_unknown.py +66 -0
- ppsspp_dfx_mcp-0.1.2/tests/mcp_inspector/test_tools_list.py +122 -0
- ppsspp_dfx_mcp-0.1.2/tests/record_replay/__init__.py +40 -0
- ppsspp_dfx_mcp-0.1.2/tests/record_replay/cassette.py +146 -0
- ppsspp_dfx_mcp-0.1.2/tests/record_replay/recording_transport.py +213 -0
- ppsspp_dfx_mcp-0.1.2/tests/record_replay/replay_transport.py +330 -0
- ppsspp_dfx_mcp-0.1.2/tests/record_replay/test_cassette_format.py +280 -0
- ppsspp_dfx_mcp-0.1.2/tests/record_replay/test_recording_transport.py +250 -0
- ppsspp_dfx_mcp-0.1.2/tests/record_replay/test_replay_transport.py +450 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/core/__init__.py +0 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/core/test_address.py +333 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/core/test_config_validate.py +54 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/core/test_launcher.py +767 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/core/test_registers_normalize.py +41 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l1_contract/__init__.py +0 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l1_contract/conftest.py +100 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l1_contract/test_breakpoint_calls.py +169 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l1_contract/test_contract_param_shapes.py +227 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l1_contract/test_cpu_calls.py +130 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l1_contract/test_disasm_calls.py +90 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l1_contract/test_gpu_calls.py +322 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l1_contract/test_hle_calls.py +107 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l1_contract/test_input_calls.py +110 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l1_contract/test_memory_calls.py +211 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l1_contract/test_r15_error_code_prefix.py +66 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l1_contract/test_replay_calls.py +212 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l1_contract/test_step_calls.py +123 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l1_contract/test_system_calls.py +95 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/__init__.py +0 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/conftest.py +71 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_address_param_type_contract.py +214 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_ai_usability_schema_contract.py +76 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_boundary_fullstack.py +259 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_boundary_semantics.py +121 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_capabilities_contract.py +121 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_completion_contract.py +197 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_defect_regression_locks.py +145 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_error_code_contract.py +164 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_error_contract.py +126 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_exposed_wrapper_structured.py +71 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_health_response_contract.py +151 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_instructions_contract.py +209 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_layering_tripwire.py +73 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_lock_contract_tripwire.py +177 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_memory_protection.py +108 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_output_schema_contract.py +425 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_query_top_n_default.py +62 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_reload_scripts_notification_contract.py +207 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_replay_registry.py +200 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_resources_prompts_contract.py +145 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_response_shape.py +79 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_schema_runtime_consistency.py +80 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_tool_annotations_contract.py +200 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_tool_registry_contract.py +311 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_tool_signature_contract.py +132 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_tool_surface_baseline.py +159 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_view_address_field_type_contract.py +336 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/test_ws_contract_coverage.py +127 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l2_mcp_contract/tool_surface_baseline.json +837 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/__init__.py +0 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/conftest.py +120 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_capability_extensions.py +161 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_capture_service_orchestration.py +344 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_confirm_step_orchestration.py +270 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_error_translation_batch5.py +266 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_extract_pc_contract.py +299 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_image_tools_persistence.py +212 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_memory_protocol_adapter.py +366 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_output_governance_batch3.py +555 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_ppsspp_log_mirror.py +109 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_queue_consumer_exclusivity.py +120 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_read_output_modes.py +164 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_reconnect_handshake.py +121 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_resilient_start.py +294 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_resolve_session_id.py +101 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_resume_stale_broadcast.py +85 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_s1_scan_pattern_cap.py +125 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_s1_step_broadcast_routing.py +208 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_safety_guards_batch4.py +756 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_scan_memory_orchestration.py +434 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_search_disasm_protocol_adapter.py +226 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_session_manager_orchestration.py +1392 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_session_restored_flag.py +99 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_session_serialization.py +166 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_session_start_wait_ready.py +110 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_session_transport_robustness.py +212 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_state_sync_batch6.py +350 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_step_pause_pc_orchestration.py +211 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_stepping_fanout.py +193 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_transport_orchestration.py +796 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_transport_resilience.py +116 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_trust_level_decisions.py +207 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_wait_ready_probe.py +136 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_with_stepping_orchestration.py +469 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_workflows_tools.py +410 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l3_orchestration/test_ws_protocol_fidelity.py +210 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/__init__.py +0 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/conftest.py +63 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_batch_background.py +683 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_batch_step_invariants.py +371 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_capture_encapsulation.py +176 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_clut_params.py +97 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_confirm_step_broadcast.py +410 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_confirm_step_single_poll.py +135 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_disasm_no_disasm_fallback.py +86 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_freeze_misjudgment_fix.py +718 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_func_remove_no_name.py +70 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_gpu_record_dump_uri.py +88 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_impl_spec_consistency.py +206 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_mem_bp_add_change.py +102 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_mem_bp_always_send_bools.py +157 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_mem_bp_size.py +95 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_memory_info_search_extent.py +80 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_memory_map_no_mapping_wrapper.py +140 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_no_silent_exception.py +154 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_optional_params_exposed.py +312 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_output_screenshot_alpha_stackwidth.py +134 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_press_button_duration_default.py +75 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_read_bytes_no_data_fallback.py +86 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_read_string_signature.py +94 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_replay_invariants.py +587 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_replay_p1_file_io.py +678 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_replay_r2r3r4.py +244 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_spec_protocol_consistency.py +128 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_state_observer_invariants.py +372 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_step_stale_broadcast_filter.py +373 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_texture_params.py +101 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_thread_param_passthrough.py +202 -0
- ppsspp_dfx_mcp-0.1.2/tests/unit/l4_regression/test_tool_debugclient_consistency.py +148 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
name: pytest (${{ matrix.os }}, py${{ matrix.python-version }})
|
|
13
|
+
runs-on: ${{ matrix.os }}
|
|
14
|
+
strategy:
|
|
15
|
+
fail-fast: false
|
|
16
|
+
matrix:
|
|
17
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
18
|
+
# 单版本策略:SDK v2 导入路径依赖 3.14 新特性(见 pyproject
|
|
19
|
+
# requires-python)。放宽到矩阵多版本前先解除该耦合。
|
|
20
|
+
python-version: ["3.14"]
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v5
|
|
24
|
+
|
|
25
|
+
- name: Setup Python ${{ matrix.python-version }}
|
|
26
|
+
uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: ${{ matrix.python-version }}
|
|
29
|
+
|
|
30
|
+
- name: Install (editable, with dev extras)
|
|
31
|
+
run: pip install -e .[dev]
|
|
32
|
+
|
|
33
|
+
- name: Sanity — entry point importable
|
|
34
|
+
run: python -c "import ppsspp_dfx_mcp; print('import ok')"
|
|
35
|
+
|
|
36
|
+
# 集成测试中需要真实 PPSSPP / ISO 的用例按设计自动 skip;
|
|
37
|
+
# 其余(单元 + 契约 + fixture 化集成)必须三平台全绿。
|
|
38
|
+
- name: Run test suite
|
|
39
|
+
run: python -m pytest tests -q
|
|
40
|
+
|
|
41
|
+
ci-ok:
|
|
42
|
+
name: ci-ok
|
|
43
|
+
needs: test
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
if: ${{ always() }}
|
|
46
|
+
steps:
|
|
47
|
+
- name: Verify all matrix legs passed
|
|
48
|
+
run: |
|
|
49
|
+
if [ "${{ needs.test.result }}" != "success" ]; then
|
|
50
|
+
echo "matrix did not fully succeed: ${{ needs.test.result }}"
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
echo "all matrix legs passed"
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# 两段式发布:
|
|
4
|
+
# 阶段一 push tag v* → 构建 + 试发布到 TestPyPI,验证无误后再进阶段二
|
|
5
|
+
# 阶段二 GitHub Release 发布 → 同一 tag 重新构建 + 正式发布到 pypi.org
|
|
6
|
+
# 两阶段共用本文件:两平台 Trusted Publisher 注册均为
|
|
7
|
+
# workflow 文件名 = pypi-publish.yml / environment = pypi(OIDC,不用 API token)。
|
|
8
|
+
# 人工门禁 = 阶段二的 Release 发布按钮;因此不要在 GitHub 的 pypi 环境
|
|
9
|
+
# 上加 Required reviewers,否则阶段一也会被卡。
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
push:
|
|
13
|
+
tags:
|
|
14
|
+
- "v*"
|
|
15
|
+
release:
|
|
16
|
+
types: [published]
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
id-token: write
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
publish-testpypi:
|
|
24
|
+
name: build & publish → test.pypi.org
|
|
25
|
+
if: github.event_name == 'push'
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
environment: pypi
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v5
|
|
30
|
+
|
|
31
|
+
- name: Setup Python
|
|
32
|
+
uses: actions/setup-python@v5
|
|
33
|
+
with:
|
|
34
|
+
python-version: "3.14"
|
|
35
|
+
|
|
36
|
+
- name: Guard — tag 与 pyproject 版本一致
|
|
37
|
+
run: |
|
|
38
|
+
TAG="${GITHUB_REF_NAME#v}"
|
|
39
|
+
FILE=$(python -c "import tomllib;print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
|
|
40
|
+
if [ "$TAG" != "$FILE" ]; then
|
|
41
|
+
echo "::error::tag v$TAG 与 pyproject.toml 版本 $FILE 不一致"
|
|
42
|
+
exit 1
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
- name: Build sdist & wheel
|
|
46
|
+
run: |
|
|
47
|
+
pip install build
|
|
48
|
+
python -m build
|
|
49
|
+
|
|
50
|
+
- name: Publish to TestPyPI
|
|
51
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
52
|
+
with:
|
|
53
|
+
# 缺省时该 action 上传到正式 PyPI;TestPyPI 必须显式指定。
|
|
54
|
+
repository-url: https://test.pypi.org/legacy/
|
|
55
|
+
|
|
56
|
+
publish-pypi:
|
|
57
|
+
name: build & publish → pypi.org
|
|
58
|
+
if: github.event_name == 'release'
|
|
59
|
+
runs-on: ubuntu-latest
|
|
60
|
+
environment: pypi
|
|
61
|
+
steps:
|
|
62
|
+
- uses: actions/checkout@v5
|
|
63
|
+
|
|
64
|
+
- name: Setup Python
|
|
65
|
+
uses: actions/setup-python@v5
|
|
66
|
+
with:
|
|
67
|
+
python-version: "3.14"
|
|
68
|
+
|
|
69
|
+
- name: Guard — tag 与 pyproject 版本一致
|
|
70
|
+
run: |
|
|
71
|
+
TAG="${GITHUB_REF_NAME#v}"
|
|
72
|
+
FILE=$(python -c "import tomllib;print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
|
|
73
|
+
if [ "$TAG" != "$FILE" ]; then
|
|
74
|
+
echo "::error::tag v$TAG 与 pyproject.toml 版本 $FILE 不一致"
|
|
75
|
+
exit 1
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
- name: Build sdist & wheel
|
|
79
|
+
run: |
|
|
80
|
+
pip install build
|
|
81
|
+
python -m build
|
|
82
|
+
|
|
83
|
+
- name: Publish to PyPI
|
|
84
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
|
|
8
|
+
# Tooling caches
|
|
9
|
+
.mypy_cache/
|
|
10
|
+
.pytest_cache/
|
|
11
|
+
.ruff_cache/
|
|
12
|
+
.coverage
|
|
13
|
+
htmlcov/
|
|
14
|
+
|
|
15
|
+
# Virtual environments
|
|
16
|
+
.venv/
|
|
17
|
+
venv/
|
|
18
|
+
|
|
19
|
+
# Local secrets (evals LLM endpoint config — never commit)
|
|
20
|
+
evals/llm_api.json
|
|
21
|
+
|
|
22
|
+
# Runtime output of the debug toolchain
|
|
23
|
+
.ppsspp-dfx/
|
|
24
|
+
|
|
25
|
+
# Editor / OS
|
|
26
|
+
.vscode/
|
|
27
|
+
.idea/
|
|
28
|
+
.DS_Store
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# 更新日志
|
|
2
|
+
|
|
3
|
+
本项目的所有显著变更将记录在此文件。
|
|
4
|
+
|
|
5
|
+
格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
|
|
6
|
+
版本遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.2] - 2026-09-17
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- MCP 握手的 serverInfo 版本改为从包元数据读取(`importlib.metadata`),
|
|
15
|
+
消除 `__init__.py` 中与 pyproject 脱节的硬编码副本——0.1.1 曾在协议层
|
|
16
|
+
自报 0.1.0。
|
|
17
|
+
- README:Windows 的 venv 创建命令更正为 `py -3.14`
|
|
18
|
+
(`python3.14` 别名在 Windows 上通常不存在)。
|
|
19
|
+
|
|
20
|
+
## [0.1.1] - 2026-09-17
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- **配置模板三件套**(`examples/`):`project.yaml` / `addresses.yaml` /
|
|
25
|
+
`scripts.manifest.yaml` 可拷贝模板,PLACEHOLDER 标注 + 逐字段语义注释,
|
|
26
|
+
独立部署时 `mkdir -p .ppsspp-dfx/config && cp examples/*.yaml
|
|
27
|
+
.ppsspp-dfx/config/` 即可起步。
|
|
28
|
+
- **预置 `.mcp.json`**:独立 checkout 的开箱即用 MCP 客户端注册。
|
|
29
|
+
- `check_env.py --check` 对 `scripts.manifest.yaml` 缺失显式告警(非阻断)
|
|
30
|
+
并给出 examples 修复路径——此前缺失会导致 `ppsspp_script_*` 工具静默消失。
|
|
31
|
+
- **README 新增「故障排查速查表」与「已知限制」**:错误码体系的症状级
|
|
32
|
+
索引 + 协议面边界的诚实汇总。
|
|
33
|
+
- **`docs/SCOPE.md`**:PPSSPP WS 事件 → 工具映射的人读版 + 刻意未工具化
|
|
34
|
+
事件清单(机器可读真相源仍为 `ws_contract.py`)。
|
|
35
|
+
- 随包 `.github/workflows/`:三平台测试矩阵(CI)与两段式发布工作流——
|
|
36
|
+
push tag `v*` 构建并试发布(内部验证),确认后发布 GitHub Release 正式
|
|
37
|
+
上架 PyPI;两阶段均为 trusted publishing(OIDC),内置 tag/版本一致性 Guard。
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- README 定位为中文社区发布;代码注释与工具 docstring 保持英文
|
|
42
|
+
(协议面被工具面基线锁定)。
|
|
43
|
+
- README 参考 deepseek-harness 的官方 README 结构重构为发布版形态:
|
|
44
|
+
PyPI 安装为主路径(含安装后的 `.mcp.json` 与命令示例),新增项目状态、
|
|
45
|
+
致谢与引用节。
|
|
46
|
+
|
|
47
|
+
## [0.1.0] - 2026-09-16
|
|
48
|
+
|
|
49
|
+
### Added
|
|
50
|
+
|
|
51
|
+
- 首个开源发布版本:41 个静态 MCP 工具(全结构化 inputSchema/outputSchema)、
|
|
52
|
+
动态诊断脚本工具(manifest 驱动)、多会话管理与楔死自愈、后台批处理、
|
|
53
|
+
原生 replay 录制回放、GPU 缓冲/纹素/CLUT 转储、HLE 内省、盲测评估体系
|
|
54
|
+
(21 场景卡 + 确定性门禁)。
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Contributing to ppsspp-dfx-mcp
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in improving the project. This document defines the
|
|
4
|
+
documentation and comment conventions every source file must follow, plus the
|
|
5
|
+
practical notes for getting a development environment running.
|
|
6
|
+
|
|
7
|
+
## Development setup
|
|
8
|
+
|
|
9
|
+
The server requires an isolated venv: it imports MCP SDK v2
|
|
10
|
+
(`mcp.server.mcpserver`), which cannot coexist with the 1.x `mcp` package that
|
|
11
|
+
many other MCP servers pin.
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# From the repository root — creates .venv/ppsspp-dfx-mcp and installs
|
|
15
|
+
# (editable, with dev extras):
|
|
16
|
+
python scripts/check_env.py --bootstrap
|
|
17
|
+
|
|
18
|
+
# Verify interpreter / SDK version / package import:
|
|
19
|
+
python scripts/check_env.py --check
|
|
20
|
+
|
|
21
|
+
# Run the test suite:
|
|
22
|
+
.venv/ppsspp-dfx-mcp/Scripts/python -m pytest tests -q # Windows
|
|
23
|
+
.venv/ppsspp-dfx-mcp/bin/python -m pytest tests -q # POSIX
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Module docstrings (file headers)
|
|
27
|
+
|
|
28
|
+
Every module opens with a short docstring that answers **what this is, why it
|
|
29
|
+
exists (only if non-obvious), and the key contract or invariant** a reader
|
|
30
|
+
must know before changing it. Rules:
|
|
31
|
+
|
|
32
|
+
1. **Length**: aim for ≤ 10 lines. A header that needs more than that usually
|
|
33
|
+
means the module is doing too much.
|
|
34
|
+
2. **No history.** Never reference when or why a change happened, no dates,
|
|
35
|
+
no change IDs (`W1 fix`, `D-19`, `R15`, `建议3`, `review issue #N`,
|
|
36
|
+
`spike U2`, `acceptance 7`, `Phase 2`, `A1/A2`…). That information lives in
|
|
37
|
+
version control.
|
|
38
|
+
3. **No dead links.** Reference only documentation that ships with the
|
|
39
|
+
project (this file, `tests/`, tool docstrings). Do not link to workspace
|
|
40
|
+
planning/analysis documents — if the underlying fact matters, state the
|
|
41
|
+
fact itself in one line instead.
|
|
42
|
+
4. **Tool modules** list the tools they expose with one line each.
|
|
43
|
+
|
|
44
|
+
Example:
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
"""Memory tool wrappers.
|
|
48
|
+
|
|
49
|
+
3 tools exposed:
|
|
50
|
+
- ppsspp_read_memory(action, ...) — aggregate read (bytes/u32/string/scan)
|
|
51
|
+
- ppsspp_write_memory(address, data, format?) — write u32 or bytes
|
|
52
|
+
- ppsspp_disassemble(address, count?) — disassemble N instructions
|
|
53
|
+
|
|
54
|
+
Reads and writes go through the session's debug client; protected ranges
|
|
55
|
+
(kernel, top.prx code) reject writes unless force=True.
|
|
56
|
+
"""
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Inline comments
|
|
60
|
+
|
|
61
|
+
A comment earns its place only when it states a constraint the code cannot
|
|
62
|
+
show: a non-obvious invariant, a race condition, a protocol quirk, an order of
|
|
63
|
+
operations that must not change.
|
|
64
|
+
|
|
65
|
+
1. **No changelog comments.** Same rule as headers — no fix IDs, no dates, no
|
|
66
|
+
issue numbers, no "this used to be X". If the old behaviour matters, the
|
|
67
|
+
constraint it produced is what you write down.
|
|
68
|
+
2. **Explain why, not what.** `# increment retry counter` is noise;
|
|
69
|
+
`# the probe must run before the handshake or PPSSPP answers with an
|
|
70
|
+
empty frame` is a comment.
|
|
71
|
+
3. Placement: own line above the code it governs.
|
|
72
|
+
|
|
73
|
+
## Tool docstrings are protocol surface
|
|
74
|
+
|
|
75
|
+
The docstring of each tool function in `src/ppsspp_dfx_mcp/tools/` is the
|
|
76
|
+
description the MCP client shows to models. It follows the
|
|
77
|
+
PURPOSE / USAGE / BEHAVIOR / RETURNS convention and is locked by a contract
|
|
78
|
+
test against a committed baseline. **Do not reword tool docstrings** in
|
|
79
|
+
refactors: changing them changes the tool surface every client sees. Treat
|
|
80
|
+
them like a public API.
|
|
81
|
+
|
|
82
|
+
## Tests
|
|
83
|
+
|
|
84
|
+
- New behaviour needs a test next to the layer it belongs to
|
|
85
|
+
(`tests/unit/…` mirroring `src/`, contract tests in
|
|
86
|
+
`tests/unit/l2_mcp_contract/`).
|
|
87
|
+
- Test names describe the behaviour they lock in; the module docstring may
|
|
88
|
+
summarise what a test file locks in, under the same no-history rules.
|
|
89
|
+
|
|
90
|
+
## Pull requests
|
|
91
|
+
|
|
92
|
+
- Keep the change surgical: every line should trace back to the purpose of
|
|
93
|
+
the PR.
|
|
94
|
+
- Run the full test suite before pushing.
|
|
95
|
+
- If a change touches tool signatures, descriptions, or output contracts,
|
|
96
|
+
regenerate the tool-surface baseline
|
|
97
|
+
(`scripts/dump_tool_surface.py`) **in the same commit** and say so in the
|
|
98
|
+
description.
|
|
99
|
+
|
|
100
|
+
## File naming
|
|
101
|
+
|
|
102
|
+
- `scripts/` executables: verb-first snake_case — `<verb>_<object>.py`
|
|
103
|
+
(`dump_tool_surface.py`, `check_env.py`, `record_fixtures.py`).
|
|
104
|
+
Private helpers take a leading underscore (`_wire.py`); data files keep a
|
|
105
|
+
descriptive name with their real extension.
|
|
106
|
+
- `evals/` modules: snake_case, one purpose per module; tests follow
|
|
107
|
+
`test_<subject>.py`.
|
|
108
|
+
- Evaluation reports are development-process artifacts and are NOT
|
|
109
|
+
committed to this repository: `report-<topic>-<YYYYMMDD>.md`.
|
|
110
|
+
|
|
111
|
+
## Test layers
|
|
112
|
+
|
|
113
|
+
`tests/unit` is organized in four layers — place a new test by what it
|
|
114
|
+
locks, not by where similar-looking code lives:
|
|
115
|
+
|
|
116
|
+
| Layer | Locks | A test belongs here when… |
|
|
117
|
+
|---|---|---|
|
|
118
|
+
| `unit/core` | Domain primitives | The pure function/class under `core/` (parsers, address math, path resolution) |
|
|
119
|
+
| `unit/l1_contract` | PPSSPP wire contract | The shape/semantics of a WS event as the transport sees it |
|
|
120
|
+
| `unit/l2_mcp_contract` | MCP tool surface | Tool signatures, descriptions, schemas, error codes, annotations |
|
|
121
|
+
| `unit/l3_orchestration` | Session/transport orchestration | Multi-component behaviour across session manager, client helper, observers |
|
|
122
|
+
| `unit/l4_regression` | One historical defect per file | A specific shipped bug must never reappear |
|
|
123
|
+
|
|
124
|
+
`tests/integration/` requires a real PPSSPP + ISO (auto-skips when absent);
|
|
125
|
+
its modules are marked `integration` + `real_ppsspp`.
|
|
126
|
+
|
|
127
|
+
## Testing conventions
|
|
128
|
+
|
|
129
|
+
- **Does-not-raise tests**: calling the function bare is accepted, but if it
|
|
130
|
+
returns a value, assert it (`assert fn(...) is None`). A bare call cannot
|
|
131
|
+
distinguish "returned None" from "returned garbage".
|
|
132
|
+
- **Patching `is_pid_alive`**: production reads it as
|
|
133
|
+
`proc.is_pid_alive(...)` (module attribute) — patch
|
|
134
|
+
`ppsspp_dfx_mcp.core.proc.is_pid_alive`, never a stale re-export.
|
|
135
|
+
- **Tool-surface baseline**: `tests/unit/l2_mcp_contract/tool_surface_baseline.json`
|
|
136
|
+
snapshots the *static* registry (41 tools). Manifest scripts add dynamic
|
|
137
|
+
`ppsspp_script_*` tools at runtime, so a live server's `tool_count` is
|
|
138
|
+
baseline + manifest count.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ppsspp-dfx-mcp contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|